筆記-你不知道的JS-原型

1 [[Prototype]]

對於默認的 [[Get]] 操做來講,若是沒法在對象自己找到須要的屬性,就會繼續訪問對象的 [[Prototype]] 鏈函數

全部普通的 [[Prototype]] 鏈最終都會指向內置的 Object.prototype。因爲全部的「普通」(內置,不是特定主機的擴展)對象都「源於」(或者說把 [[Prototype]] 鏈的頂端設置爲)這個 Object.prototype 對象,如:toString,valueOf,hasOwnProperty,isPrototypeOfspa

var anotherObject = { a:2};
// 建立一個關聯到 anotherObject 的對象
var myObject = Object.create( anotherObject ); 
// myObject = { __proto__: {  a:2, __proto__: Object}};
myObject.a; // 2

屬性屏蔽prototype

給一個對象設置屬性並不單單是添加一個新屬性或者修改已有的屬性值,如myObject.foo = "bar";3d

若是 myObject 對象中包含名爲 foo 的普通數據訪問屬性,這條賦值語句只會修改已有的屬性值。code

若是 foo 存在於原型鏈上層,賦值語句 myObject.foo = "bar" 的行爲就會有些不一樣。對象

若是屬性名 foo 既出如今 myObject 中也出如今 myObject 的 [[Prototype]] 鏈上層,那麼就會發生屏蔽。myObject 中包含的 foo 屬性會屏蔽原型鏈上層的全部 foo 屬性,由於myObject.foo 老是會選擇原型鏈中最底層的 foo 屬性。blog

若是 foo 不直接存在於 myObject 中而是存在於原型鏈上層時 myObject.foo = "bar" 會出現的三種狀況。圖片

若是在[[Prototype]]鏈上層存在名爲foo的普通數據訪問屬性(參見第3章)而且沒有被標記爲只讀(writable:false),那就會直接在 myObject 中添加一個名爲 foo 的新屬性,它是屏蔽屬性。原型鏈

若是在[[Prototype]]鏈上層存在foo,可是它被標記爲只讀(writable:false),那麼沒法修改已有屬性或者在 myObject 上建立屏蔽屬性。若是運行在嚴格模式下,代碼會拋出一個錯誤。不然,這條賦值語句會被忽略。總之,不會發生屏蔽。開發

若是在[[Prototype]]鏈上層存在foo而且它是一個setter(參見第3章),那就必定會調用這個 setter。foo 不會被添加到(或者說屏蔽於)myObject,也不會從新定義 foo 這個 setter。

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

2 「類」

構造函數+原型函數,兩個函數經過 constructor 屬性和 prototype 屬性相關聯。

類關係

function Foo() {}
let foo = new Foo();

1 foo instanceof Foo

instanceof 操做符的左操做數是一個普通的對象,右操做數是一個函數。instanceof 回答的問題是:在 a 的整條 [[Prototype]] 鏈中是否有指向 Foo.prototype 的對象

2 Foo.prototype.isPrototypeOf( foo )

isPrototypeOf(..) 回答的問題是:在 foo 的整條 [[Prototype]] 鏈中是否出現過 Foo.prototype 。咱們也能夠直接獲取一個對象的 [[Prototype]] 鏈。Object.getPrototypeOf(foo); 如Object.getPrototypeOf( foo ) === Foo.prototype; // true 或者 a.__proto__ === Foo.prototype; // true
圖片描述

相關文章
相關標籤/搜索