高程是这样定义数据属性的:数据属性包含一个数据值的位置。在这个位置能够读取和写入值,数据属性有四个描述其行为的特性。(第三版6.1.1节,P139)测试
这里引用高程上的详细解释(第三版6.1.1节,P139)this
[[Configurable]]:表示可否经过delete删除属性从而从新定义属性,可否修改属性的特性,或者可否把属性修改成访问器属性。对于直接在对象上定义的属性,它们的这个特性默认为true [[Enumerable]]:表示可否经过for-in循环返回属性。对于直接在对象上定义的属性,这个特性默认值为true [[Writable]]:表示可否修改属性的值。对于直接在对象上定义的属性,他们的这个特性默认为true [[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读,写入属性值的时候,新值保存在这个位置。这个特性默认为undefined 当修改configurable属性为false的时候,则该属性被认为是不可配置的,而且没有属性能够被改变(除了单项修改writable为false);
Q1:如今存在一个问题,若是修改configurable属性为false,那么根据解释,只能单向修改writable为false,那么若是writable为true,可否改变属性的值?spa
根据高程上的描述,值也算一个特性,理论上值不能被修改,可是实际上值是能够被修改的,你们看下面的例子:code
var a = {b:'aa',c:'dd'}; a.b = 'cc'; Object.defineProperty(a,'b',{ configurable:false }); Object.defineProperty(a,'b',{ value:'dd' }); console.log(a); //{ b: 'dd', c: 'dd' } a.b = 'ee'; console.log(a); //{ b: 'ee', c: 'dd' }
可是若是将wirtable修改成false就不能被修改值了,以下例子(接着上边)对象
Object.defineProperty(a,'b',{ writable:false }); a.b = 'ff'; console.log(a); //{ b: 'ee', c: 'dd' }
因此能够这么理解,configurable属性是控制configurable属性自己、enumerable和writable这三个特性的。 而writable是控制value这个特性的,将configurable设置为false并不影响value的可改变性,value是否可改变只与writable有关。ip
四个:ci
[[configurable]] [[Enumberable]] [[get]] [[set]]
高程上的解释和详细定义就不赘述了。get
有一点须要解释一下,根据高程的上的一个例子,我作了一个相似的例子it
var book = { _year:2004, edition:1 }; Object.defineProperty(book,'year',{ get:function () { return this._year; }, set:function (v) { this._year = v+1; } }); console.log(book._year); //能够直接访问以_year开头的属性,事实上这个和普通属性没什么区别! console.log(book.year); book.year = 2332; console.log(book.year);
高程上解释:以_开头的属性是访问器属性,事实上没有语法的规定,但这是约定俗成的;虽然能够直接访问以_开头的属性,可是做为这个模块的使用者,应该只是访问同名的不带_的属性;做为这个模块的编写者,应该编写一个同名的不带_的属性做为访问器。好比year就是_year属性的访问器。io
Q2:还有一个问题,若是在设置属性的时候同时指定访问器属性和数据属性会发生什么?
测试了一下,会报错:
Object.defineProperty(book,'year',{ get:function () { return this._year; }, set:function (v) { this._year = v+1; }, value:'22' }); //TypeError: Invalid property descriptor. Cannot both specify accessors(构造器) and a value or writable attribute, #<Object>
最后,一旦将configurable指定为false,4个访问器属性都没法再修改了。
2.1 读取属性的特性
利用Object.getOwnPropertyDescriptor(object,object.name)来返回一个为object.name量身定作的描述符对象。含有该属性的特性信息。
有三种不一样程度的防篡改级别
用一张表能够解释防篡改的程度
添加新的属性/方法 configurable writable 不可扩展 × √ √ 密封 × × √ 冻结 × × ×
检测是否不可扩展:Object.isExtensiable(object) 检测是否密封: Object.isSealed(object) 检测是否冻结: Object.isFrozen(object)