js面向對象之屏蔽屬性

1.什麼是屏蔽屬性

一條賦值語句引出的思考:html

myObject.foo = "bar";

若是myObject 對象中包含名爲foo 的普通數據訪問屬性,這條賦值語句只會修改已有的屬
性值。
若是foo 不是直接存在於myObject 中,[[Prototype]] 鏈就會被遍歷,相似[[Get]] 操做。
若是原型鏈上找不到foo,foo 就會被直接添加到myObject 上。
然而,若是foo 存在於原型鏈上層,賦值語句myObject.foo = "bar" 的行爲就會有些不一樣
(並且可能很出人意料)。稍後咱們會進行介紹。
若是屬性名foo 既出如今myObject 中也出如今myObject 的[[Prototype]] 鏈上層, 那
麼就會發生屏蔽。myObject 中包含的foo 屬性會屏蔽原型鏈上層的全部foo 屬性,由於
myObject.foo 老是會選擇原型鏈中最底層的foo 屬性。code

2.屏蔽比咱們想象中更加複雜

下面咱們分析一下若是foo 不直接存在於myObject 中而是存在於原型鏈上層時myObject.foo = "bar" 會出現的三種狀況。htm

  1. 若是在[[Prototype]] 鏈上層存在名爲foo 的普通數據訪問屬性而且沒有被標記爲只讀(writable:false),那就會直接在myObject 中添加一個名爲foo 的新屬性,它是屏蔽屬性。
  2. 若是在[[Prototype]] 鏈上層存在foo,可是它被標記爲只讀(writable:false),那麼沒法修改已有屬性或者在myObject 上建立屏蔽屬性。若是運行在嚴格模式下,代碼會拋出一個錯誤。不然,這條賦值語句會被忽略。總之,不會發生屏蔽。
  3. 若是在[[Prototype]] 鏈上層存在foo 而且它是一個setter(參見第3 章),那就必定會調用這個setter。foo 不會被添加到(或者說屏蔽於)myObject,也不會從新定義foo 這個setter。

3.你所不知道的屏蔽屬性

大多數開發者都認爲若是向[[Prototype]] 鏈上層已經存在的屬性([[Put]])賦值,就必定會觸發屏蔽,可是如你所見,三種狀況中只有一種(第一種)是這樣的。
若是你但願在第二種和第三種狀況下也屏蔽foo,那就不能使用= 操做符來賦值,而是使用Object.defineProperty(..)(參見第3 章)來向myObject 添加foo。對象

4.JavaScript中的屬性:定義和賦值的區別

1.賦值可能會調用原型上的setter(sub與sup裏面有同名屬性),定義會建立一個自身屬性blog

2.原型鏈中的同名只讀屬性可能會阻止賦值操做(如上的非屏蔽操做),但不會阻止定義操做ip

3.賦值運算符不會改變原型鏈上的屬性原型鏈

4.只有經過定義操做,才能建立一個擁有指定特性的屬性(Object.defineProperty的威力)開發

5.對象字面量中的屬性是經過定義操做添加的get

瞭解更詳細的信息能夠參考:http://www.cnblogs.com/ziyunf...原型

相關文章
相關標籤/搜索