ECMA-262为JavaScript引擎的实现定义了这些特性,所以它们不能直接在JavaScript中访问。为了表明属性是内部值,规范将它们括在双方括号中,例如[[Enumerable]]。ECMAScript中有两种属性:数据属性和访问器属性。1.数据属性数据属性包含数据值的位置。可以在这个位置读写值。一个数据属性有4个属性来描述它的行为。[[Configurable]]:表示是否可以通过delete删除属性重新定义属性,是否可以修改属性的属性,或者是否可以将属性更改为访问器属性。直接在对象上定义的属性,如前面的示例,将此属性默认为true。[[Enumerable]]:表示是否可以通过for-in循环返回一个属性。直接在对象上定义的属性,如前面的示例,将此属性默认为true。[[Writable]]:表示属性的值是否可以修改。直接在对象上定义的属性,如前面的示例,将此属性默认为true。[[Value]]:包含此属性的数据值。读取属性值时,从该位置开始读取;写入属性值时,将新值保存在该位置。此功能的默认值为undefined。对于前面示例中直接在对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]和[[Writable]]属性都设置为true,而[[Value]]属性设置为指定值。例如:varperson={name:"Nicholas"};这里创建了一个名为name的属性,分配给它的值为“Nicholas”。也就是说,[[Value]]属性将设置为"Nicholas",对此值的任何修改都将反映在此位置。要修改属性的默认属性,必须使用ECMAScript5Object.defineProperty()方法。该方法采用三个参数:属性所在的对象、属性的名称和描述符对象。其中,描述符(descriptor)对象的属性必须是:configurable、enumerable、writable和value。设置这些值中的一个或多个来修改相应的属性值。例子:varperson={};Object.defineProperty(person,“name”,{writable:false,value:“Nicholas”});警报(人名);//“尼古拉斯”person.name=“Greg”;alert(person.name);//“Nicholas”示例创建一个名为name的属性,其值为“Nicholas”是只读的。此属性的值是不可变的。如果你试图给它赋一个新值,赋值操作在非严格模式下会被忽略;在严格模式下,赋值操作会导致抛出错误。类似的规则适用于不可配置的属性。示例:varperson={};Object.defineProperty(person,“name”,{configurable:false,value:“Nicholas”});alert(person.name);//“尼古拉斯”deleteperson.name;alert(person.name);//"Nicholas"将configurable设置为false,表示不能从对象中删除该属性。如果你在这个属性上调用delete,在非严格模式下什么也不会发生,但在严格模式下会导致错误。此外,一旦属性被定义为不可配置的,就无法将其更改回可配置的。此时调用Object.defineProperty()方法修改writable以外的属性会报错:varperson={};Object.defineProperty(person,“name”,{configurable:false,value:“Nicholas”});//抛出错误Object.defineProperty(person,“name”,{configurable:true,value:“Nicholas”});也就是说,可以多次调用Object.defineProperty()方法来修改同一个属性,但是将configurable属性设置为false后就有限制了。如果在调用Object.defineProperty()方法时未指定,则configurable、enumerable和writable属性默认为false。在大多数情况下,可能没有必要利用Object.defineProperty()方法提供的这些高级功能。但是,理解这些概念对于理解JavaScript对象非常有用。IE8是第一个实现Object.defineProperty()方法的浏览器版本。然而,这个版本的实现有一些限制:这个方法只能用于DOM对象,并且只能创建访问器属性。由于实现不完整,建议读者不要在IE8中使用Object.defineProperty()方法。
