Javascript中對象的Obeject.defineProperty()方法-------------(ES5/我的理解)

在講到Obeject.defineProperty()方法以前先得說明一下ECMAScript中有兩種屬性:數據屬性訪問器屬性 javascript

兩種屬性存在的意義:描述對象屬性(key)的一些特性,由於這些屬性是內部值,通常放到 [[兩個中括號]]  中。vue

 

Object.defineProperty(obj , 'key' , {描述信息,是個對象,相似配置項} )  方法接收三個參數,屬性所在的對象屬性名 和一個描述符對象java

數據屬性的描述符是下面的一個或者多個(configurable、enumerable、writable 和 value)數組

訪問器屬性的描述符是如下的一個或多個(configurable、enumerable、get 和 set)框架

 

經過 Object.defineProperty() 方法,能夠建立數據屬性(並設定其內部屬性),也能夠建立訪問器屬性(訪問器屬性包含 getter 和 setter函數)函數

 

數據屬性的各項解釋:spa

enumerable : 可枚舉性,是否能經過for-in或者Object.keys來遍歷prototype

 

writable : 可修改(可寫入),是否能修改value屬性值3d

 

value : 屬性的屬性值  (讀出和寫入都是從這裏讀出和保存的),默認undefined    數據屬性是能夠直接經過  對象.屬性obj.key 的形式訪問和賦值雙向綁定

 

configurable : 是否可配置,當它爲false的時候,一、上面三項的true和false值都不能改變了,二、對象自己也不能經過delete來刪除三、數據屬性和訪問器屬性也不能來回轉化了

 

 

訪問器屬性的各項解釋:

configurable 、enumerable同上

get : 讀取屬性的時候調用,默認值undefined

set : 設置屬性的時候調用,默認值undefined

 

對比數據屬性和訪問器屬性的屬性異同

 

數據屬性做用:   修改屬性默認的特性 (會新建出數據屬性)

訪問器的做用:  訪問和設置數據屬性的屬性值,不會建立出  .

 

一、對象屬性建立對比-----   這裏建立的是數據屬性不是訪問器屬性,訪問器屬性只有一種建立方式

A、字面量建立對象的形式:var obj = {key : value }                ------   var person1 = {age : 3}  直接建立了age屬性和屬性值

B、Object.defineProperty(obj ,'key' {...} )建立對象               ------   var person2 = {};   Object.defineProperty(person2, "age", { value: 3 }); 

經過統一的操做 :

①  console.log(person1 .name)   ②  person1.age = 4   ③   console.log(person1 .name)   得出  // 3 , 4   賦給了新的值

①  console.log(person2 .name)   ②  person2.age = 4   ③   console.log(person2 .name)   得出  // 3 , 3   賦值沒有成功

原理:

直接在對象上定義的屬性var obj = {key : value }(字面量形式和new Object()形式) ,它們的Configurable、Enumerable 和Writable特性都被設置爲 true,而Value特性被設置爲指定的值

經過 Object.defineProperty()定義的屬性 它們的Configurable、Enumerable 和Writable特性都被設置爲 false,而Value特性被設置爲指定的值,這時候的屬性值是隻讀的

 

 

 

二、重點:數據屬性不只能夠直接訪問和設置(對象.屬性/obj.key的形式),也能夠經過定義的訪問器(getter setter)來專門訪問和設置

 

得出結論:

① 經過發現book下面並無真正的year屬性,證實了數據屬性並不能根據訪問器屬性來定義建立,訪問器屬性只是操做訪問器屬性,這個屬性能夠理解爲是在get和set這一動態讀取和設置的過程當中發揮做用。

setget是一對勾子(hook)函數,要理解觸發機制(是根據調用book.year或者設置book.year=2005這個時間點觸發的,因此這個year能夠隨便取值):就是訪問器屬性在調用時,實際上對應觸發訪問器屬性中定義的 get 方法(最後返回的值是其中return出來的結果),當對一個對象的某個屬性賦值時,則會自動觸發調用相應的set函數。(若是不瞭解運行機制,須要打斷點走一遍便可)

③ book只有_year和edtion兩個數據屬性(是否是數據屬性,要看帶不帶value屬性),year不是數據屬性(訪問屬性不包含數據值,也不會顯式的寫出來),可是可是book.hasOwnProperty("year"); 確實返回 true。說明了訪問器屬性也屬於對象本身添加的屬性。只是讀寫方式和普通的不同。

④ _year帶有下劃線的屬性,表示只能經過  對象方法 訪問的屬性。( 有待補充。。。。)

 

三、再來擼一遍代碼,看看運行的原理具體是怎樣的??

 

訪問器將真正存值的變量隱藏起來,並提供對外的接口,當你讀取或設置屬性時,可執行必定的操做:
 

 

上列中set的參數就是你設置的值。從外部看,你設置man.age的方式與賦值無異,這與el.style.color = "red"類似:看上去是簡單的賦值,卻觸發了必定行爲(設置DOM文本爲紅色)。

  

四、怎麼區分數據屬性仍是訪問器屬性???看裏面的描述符對象。二者是不能混用的。

 

 

五、js中的屬性的理解: 

javascript中一共有三種屬性:

普通屬性:也就是常規的數據屬性,這種屬性是用戶來添加修改等,把它設置成什麼樣,就返回出來什麼樣,不會作些額外的事情。 var obj ={name : "yang"};那麼console.log(obj.name) //yang

內部屬性:好比數組arr的length屬性,函數的prototype屬性,DOM節點的innerHTML屬性,用戶賦完值之後,取值的時候,不必定按預期,有時候還會額外的作一些事情,也難以改變他們的行爲。

    好比說某一數組,它的長度爲10, 當咱們設置它爲11時,它就會增長一個undefined元素,再設置爲9時,就會從後面刪掉兩個元素。

    函數的prototype若是被改變,至關於將其父類改變了,會new不一樣類型的實例。

    DOM的innerHTML,咱們賦值時是一個字符串,再取出時,這字符串可能會與原來的不同, 而且在原元素上生成了不同的子節點。

訪問器屬性,容許用戶在賦值或取值都通過預先設定的函數,從而實現內部屬性的那一種特殊效果。

 

六、應用(能夠代替對象中的getter和setter函數)

    ==    

 

其餘地方:vue框架MVVM的數據雙向綁定,數據的實時觀察,不一樣於angular使用的髒檢查。

 

 七、和Object.defineProperty()相關的一些對象方法。

obj.propertyIsEnumerable('key')

obj.hasOwnProperty('key')    能夠檢測出訪問器屬性

Obeject.getOwnpropertyDescriptor(obj , 'key')   或者描述符對象  -----   有就返回對象,不然是undefined。

Object.keys(obj)方法,遍歷key值 。   當Object.defineProperty()中enumerable爲false的時候,是遍歷不出來的。

 

八、其餘

Obeject.prototype的configurable是false,表明不可配置

對象obj的toString方法是原型鏈上的是不可枚舉的   obj.propertyIsEnumerable(toString')     // false 

  

 

最後:不要再IE8 及之前版本 中使用 Object.defineProperty() 

相關文章
相關標籤/搜索