JavaScript学习笔记5 面向对象之理解对象

来源:互联网 发布:免费淘宝一键复制宝贝 编辑:程序博客网 时间:2024/05/18 19:20

在HTML中使用JavaScript(此段补充之前没写的内容)

<script>标签的属性 - async 表示应该立即下载脚本,但不妨碍页面中的其他操作(异步执行),比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效 - charset 设置字符集 基本浏览器被忽略,很少人用 - defer 表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。 - language 已废弃 - scr 表示包含要执行代码的外部文件 - type language的替代属性;表示编写代码使用的脚本语言的内容类型。text/javascript和text/ecmascript都已经不被推荐使用。但是考虑到约定俗成和最大限度的浏览器兼容性,目前type的属性仍是text/javascript  不设置 type 属性 默认为text/javascript.建议使用src 引入JS文件,好处如下: 1. 可维护性:所有JS文件放在同一个文件夹下,可以集中精力写JS代码,不用去考虑HTML 2. 可缓存:如果有两个页面使用同一个JS文件,那么这个文件只需要被下载一次,能够加快页面对的加载速度 3. 适应未来,通过外部文件来包含JavaScript无须使用前面提到XHTML或注释back.HTML和XHTML包含外部文件的语法都是相同的。

面向对象的程序设计

  • 理解对象
  • 属性类型

    • 数据属性
      • Configurable
      • Enumerable
      • Writable
      • Value
    • 访问器属性
      • Configurable
      • Enumerable
      • Get
      • Set
  • 读取属性的特性Object.getOwnPropertyDescriptor()

理解对象

创建一个自定义对象的最简单方式就是创建一个Object的实例,然后再为它添加数据和方法如下:

var person=new Objcet();person.name="Nicholas";person.age=29;person.job="Software Engineer";person.setName=function(){    alert(this.name);};

早期的程序员使用这种模式创建新对象,后来用如下模式:(对象字面量)

var person={    name:"Nicholas",    age:29,    job:"Software Engineer",    sayName : function(){        alert(this.name);    }};

两种方式创建的对象一样,都有相同的属性和方法。这些属性在创建时都会带有一些特征值,JavaScript通过这些特征值来定义他们的行为

属性类型

ECMA-262第五版在定义只有内部才用的特性时,描述了属性(property)的各种特征。ECMA-262定义这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问他们。为了表示特性是内部值,该规范把他们放在了两队方括号中,列入[[Enumerable]]。

ECMAScript中有两种属性:数据属性和访问器属性

数据属性(有4个描述其行为的特性)

  • [[Configurable]]: 表示能否通过delete删除属性,从而重新定义属性,能否修改属性的特性、能否把属性修改为访问器属性。 像前面例子中那样直接在对象上定义的属性,他们的这个特性默认为true。
  • [[Enumerable]]:表示能否通过 for-in循环返回属性。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true.( for in循环请参考 http://www.w3school.com.cn/js/js_loop_for_in.asp)
  • [[Writable]]:表示能否修改属性的值,像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true.
  • [[Value]]:包含属性的数据值。读取属性值得时候,从这个位置读;写入属性值得时候,把新值保存在这个位置。这个特性的默认值为undefined。
    例如:
 var person={     name:"Nicholas" };

name 的属性类型是 数据属性
行为特性值为
[[Configurable]] =true 可配置的
[[Enumerable]] =true 可列举的;
[[Writable]] =true 可写的
[[Value]] =”Nicholas”
如果 person.name=”123”;
则[[Value]] =”123”;
要想修改属性默认的特征,必须使Object.defineProperty()方法 ,传三个参数 1.属性所在对象,2.属性名,3.一个描述符对象,描述符对象的属性必须是:configurable、enumerable、writable和value 。设置其中的一或多个值,可以修改对应的特性值。例如:

Object.defineProperty(person,"name" ,{    writable:false,//设置可写为false   (只读)    value:"Nicholas"});alert(person.name);//Nicholasperson.name="111"; //在非严格模式下,赋值操作将被忽略;在严格模式下会抛出错误alert(person.name);Nicholas

类似规则也适用于不可配置的属性(configurable)

var person={};Object.defineProperty(person,"name",{    //表示不能从对象中删除属性,如果这个属性调用delete    //非严格模式下将被忽略    //严格模式下抛出异常    //一旦修改为不可配置的,就不能再变回可配置了    //此时再调用Object.defineProperty()方法修改出了writable之外的特性,都会导致错误 抛出异常    configurable:false,       value:"Nicholas"});alert(person.name);//Nicholasperson.name="111"; alert(person.name);//Nicholas// person 为不可配置  抛出异常Object.defineProperty(person,"name",{    configurable:true,       value:"Nicholas"});
  • 可以多次调用Object.defineProperty()方法修改同一个属性,但在把configruable属性设置为false之后就会有限制了。
  • 在调用Object.defineProperty()方法时,如果不指定configruable、enumerable和writable特性,默认值都是false. 多数情况下都没有必要利用Object.defineProperty()方法提供的这些高级功能。不过,理解这些概念对理解JavaScript对象却非常有用。

访问器属性

访问器属性不包含数据值;它们包含一对getter和setter函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。
访问器属性有如下4个特性
- [[configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,此特性默认值为true。
- [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性,此特性默认为true
- [[Get]]:在读取属性时调用的函数。默认值为undefined.
- [[Set]]:在写入属性时调用的函数。默认值为undefined.
访问器属性不能直接定义,必须使用Object.defineProperty()定义。请看下面的例子。

var book={    // 一般私有变量 会加下划线    _year:2004,    edition:1};//创建一个 名为year的访问器   包含 getter  setter 函数 这是访问器属性最长用的方式//即设置一个属性的值,会导致其他属性发生变化Object.defineProperty(book,"year",{    get : function(){        return this._year;    },    set : function(newValue){        if(newValue>this._year){            this.edition+=newValue-this._year;            this._year=newValue;        }    }});alert(book.year);//2004book.year=2005;alert(book.edition);//2book.year=2007;alert(book.edition);//4alert(book.year);//2007alert(book._year);//2007

不一定非要同时指定getter和setter

  • 只指定getter意味属性时不能写,非严格:没指定getter函数,尝试写入属性时会被忽略。严格:会抛出错误。
  • 只指定setter意味不能读,非严格返回undefined 。严格:抛出错误。

    在不支持Object.defineProperty()方法的浏览器中不能修改[[Configurable]] 和[[Enumerable]]。

    定义多个属性

    由于为对象定义多个属性的可能性很大,ECMAScript又定义了一个Objcet.defineProperties()方法。利用这个方法可以通过描述符一次定义多个属性。

var book={};Object.defineProperties(book,{    _year:{        configurable:true,        writable:true,        value :2004    },    edition:{        configurable:true,        writable:true,        value:1    },    year:{        get : function(){            return this._year;        },        set : function(newValue){            if(newValue>this._year){                this.edition+=newValue-this._year;                this._year=newValue;            }        }    }});//这种写法只设置 _year edition   value的值  没有设置 configurable  writable enumerable,默认为//设置后alert(book.year);//2004book.year=2005;alert(book.edition);//2book.year=2007;alert(book.edition);//4alert(book.year);//2007alert(book._year);//2007//没有设置 configurable  writable  不可配置 不可写 结果为alert(book.year);//2004book.year=2005;alert(book.edition);//1book.year=2007;alert(book.edition);//1alert(book.year);//2004alert(book._year);//2004

读取属性的特性

使用ECMAScript5的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。
返回值是一个对象
如果传入访问器属性 对象值有:
configurable、enumerable、get和set
如果是 数据属性 对象值有:
configurable、enumerable、writable和value

var book={};Object.defineProperties(book,{    _year :{    configurable:true,    value:2004}, edition :{    value:1 },  year : {    get : function(){        return this._year;    },    set : function(newValue){    }  }});  var descriptor=   Object.getOwnPropertyDescriptor(book,"_year");  alert(descriptor.value);//数据属性"_year" 的value值是初始值 2004    alert(descriptor.configurable);//数据属性"_year"的configurable值为注初始值true  alert(descriptor.writable);//数据属性"_year"的writable值为默认值false  alert(typeof descriptor.get);//数据属性"_year" 未定义get  undefined  //year 和 _year 不是一样  var descriptorYear= Object.getOwnPropertyDescriptor(book,"year"); alert(descriptorYear.value);//访问器属性 "year" undefined   alert(descriptor.enumerable);////访问器属性 "year" enumerable 默认值为  false alert(typeof descriptorYear.get)//访问器属性 "year" get 是一个指向getter函数的指针
0 0