什麼是原型鏈
原型鏈是利用原型,讓一個引用類型繼承另一個 引用類型的屬性和方法。
爲了說明白原型鏈,需要從構造函數、原型與實例的關係講起。
構造函數、原型與實例的關係:
- 每個構造函數都有一個原型對象,
- 原型對象都包含一個指向構造函數的指針(顯式原型),
- 而實例都包含一個指向原型對象的內部指針(隱式原型)。
那麼,假如讓原型對象等於另一個類型的實例,結果會讓此事的原型對象包含一個指向另一個原型的指針,相應地,另一個原型中也包含着指向另一個構造函數的指針。
假如另一個原型又是另一個類型的實例,那麼上述關係依然成立。
如此層層遞進,就構成了實例與原型的鏈條。
這就是原型鏈的基本概念。
JavaScript 只是在對象之間創建關聯,所以兩個對象之間的關係並不是複製而是委託。
所以,相比之下,說委託比繼承更合適。
顯式原型:
- 每一個函數在創建之後都會擁有一個名爲
prototype
的屬性,這個屬性指向函數的原型對象。
隱式原型:
- JavaScript 中任意對象都有一個內置屬性
[[prototype]]
- 在ES5之前沒有標準的方法訪問這個內置屬性,但是大多數瀏覽器都支持通過
__proto__
來訪問。 - ES5 中有了對於這個內置屬性標準的 Get 方法
Object.getPrototypeOf()
Object.prototype
這個對象是個例外,它的proto值爲null
圖片描述
代碼描述
function Person() {}
person = new Person();
console.log(person.__proto__ === Person.prototype);
console.log(Object.getPrototypeOf(person) === Person.prototype);
console.log(person.constructor === Person); // 注①
console.log(Person.prototype.__proto__ === Object.prototype); //注②
console.log(Object.prototype.__proto__ === null);
console.log(Person.prototype.constructor === Person);
console.log(Object.__proto__ === Function.prototype); //注③
console.log(Function.prototype.__proto__ === Object.prototype);
輸出全是 true
注
① person.constructor === Person.prototype.constructor
原型鏈
② Person.prototype 是對象,是 Object 類型的實例
③ Object 是構造函數,於是它是 Function 的實例,其內部有 [[proto]]
指向實例的原型