天天看點

你不知道的js -- 原型

JavaScript中所有的對象都有一個[[ prototype ]] 的内置屬性,其實就是其他對象的引用。在你引用對象的屬性時,會觸發[[ GET ]]操作,會在目前的作用域裡邊尋找是否存在這個屬性,如果沒有就往上尋找。這個過程就是對象prototype的鍊式操作。

prototype的對象盡頭就是Object.prototype 

Object.prototype裡邊到底有什麼:

你不知道的js -- 原型

一些常用的toString()、valueOf() 方法。

屬性的設定與屏蔽

一個簡單的指派操作: obj.foo = 'bar';可能會發生以下三種可能。

1、在 prototype 鍊上存在 foo 屬性,但是資料通路屬性沒有被标記為可讀writable:false;

那麼js就直接在你的obj中建立一個新的foo 的屬性并指派為 “bar”,這就是屏蔽屬性。

2、如果在prototype 上面有foo,且被标記為writable: false,那麼js無法修改已有屬性或在obj上建立新的foo 。浏覽器在嚴格模式下還會抛出一個錯誤,這條指派會被忽略,不被執行最後。

3、如果在prototype上存在 foo 屬性,而且他是一個setter,那就一定會調用這個setter,foo 不會被重新定義在obj中而且不會添加到obj。

這些情況會産生屏蔽:

你不知道的js -- 原型
你不知道的js -- 原型

myObj.val ++ 操作相當于myObj.val = myObj.val + 1,++ 操作會先從prototype上面查找val這個屬性,然後從obj1上面找到了這個val并執行val = val+ 1;接着用[[ PUT ]]操作把指派後的val賦給myObj。

總結:

如果要通路一個對象中并不存在的屬性,[[GET]]操作就會自動查找内部prototype 關聯的對象上面去找,一直到Object.prototype鍊上面去找。

所有的普通對象都有内置的prototype ,指向原型鍊的頂端,是以一些常用的toString()和valueOf()方法能在普通對象中使用。

關聯兩個對象常用的方法是new 關鍵字進行函數調用,使用new調用函數的時候會把新對象的prototype屬性關聯到其他對象,帶new 的函數調用通常叫做“構造函數調用”,但是本質上和一些傳統意義上的類構造函數是不一樣的。

繼續閱讀