高程是這樣定義數據屬性的:數據屬性包含一個數據值的位置。在這個位置能夠讀取和寫入值,數據屬性有四個描述其行爲的特性。(第三版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)