JavaScript——原型和原型鏈

原型對象

所有的函數都會有一個prototype屬性,這個屬性是公有且不可枚舉的。它會指向一個對象,而這個對象則被稱爲該函數的原型對象:

function Foo() {
  // ...
}
Foo.prototype;  // {}

在默認的情況下,所有的原型對象都有一個constructor屬性,這個屬性包含一個指向prototype屬性所在函數的指針。拿之前的例子來講,Foo.prototype.constructor指向Foo。創建了自定義函數後,其原型對象默認只有一個constructor屬性,而其他的方法都是從Object繼承而來,當把該函數當作構造函數進行實例化的時候(使用new操作符),創建的實例內部包含一個指針[[Prototype]],指向構造函數的原型對象。

function Person(name) {
  this.name = name;
}
var person1 = new Person('cherry');
var person2 = new Person('Nick');
person1.name; // cherry
person2.name; // Nick

下圖展示了各個對象之間的關係:
在這裏插入圖片描述
這個圖展示了PersonPerson的原型對象Person的兩個實例之間的關係,從圖中可以看出,Person.prototype屬性指向Person的原型對象,而Person的原型對象constructor屬性指向Person函數Person的每個實例person1person2內部都有一個[[Prototype]]屬性,指向Person的原型對象

原型鏈

什麼是原型鏈

回顧一下上面描述的構造函數,原型和實例之間的關係。每個構造函數都有一個原型對象,而每個實例中又包含一個指向原型對象的指針,如果我們將原型對象等於另外一個構造函數的實例,那麼這個原型對象就會包含一個指向另一個原型對象的指針,這樣層層遞進,就構成了實例和原型之間的鏈條,而這個鏈條就是原型鏈。

原型鏈的作用

我們知道在JavaScript中,在引用對象的屬性時,會觸發對象的[[Get]]操作,對於默認的[[Get]]操作來說,第一步就是檢測對象本身是否有該屬性,如果有就引用它。但如果該屬性不在對象本身中,此時就需要檢查[[Prototype]]鏈了。

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

Object.create(…) 會創建一個 對象並把這個對象的 [[Prototype]] 關聯到指定的對象

但是如果anotherObject中也沒有a屬性的並且[[Prototype]]鏈不爲空,這個查找過程就會順着[[Prototype]]鏈繼續下去。

這個過程會持續到找到匹配的屬性名或者查找完整條[[Prototype]] 鏈。如果是後者的話,[[Get]]操作的返回值是undefined

原型鏈的盡頭

所有普通的[[Prototype]]鏈的盡頭都是Object.prototype

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章