原文:【Javascript 基礎】原型鏈(你的 star 是對我寫作的「正反饋」)。
一、當初,為什麼要為 JS 設計原型鏈?
當初,設計 Javascript這門語言時,作者既想該語言擁有「萬物皆物件」的優點,又不想加入類的概念來增加語言的複雜度。
因此,作者提出了原型鏈(prototype chain)的概念,用來「連線」多個物件,使多個物件可以共享同一份變數,讓「繼承」成為了可能。
二、__proto__、prototype、constructor 各自代表了什麼?
__proto__
: 通常指向當前物件對應的建構函式中的prototype
,所有的物件都會有這個屬性。
這裡的「通常」指的是「非JS內建的物件」。而對於「JS內建的物件」,我建議:「硬記」~
-
prototype
: 這就是所謂的原型,只有建構函式才有該屬性。 -
constructor
: 生成當前物件的建構函式,所有物件都有建構函式。
相較於那些枯燥的等式,結合下圖,或許能夠更快的理清各種的連線關係。
三、JS 物件的尋值邏輯
四、幾個衍生出來的面試題
- 能否寫一個與
New
關鍵字功能類似的NEW
方法 ?
function NEW(fn) {
if (!fn.prototype) {
throw('不是建構函式');
return;
}
var obj = {};
var args = Array.prototype.slice.call(arguments, 1);
obj.__proto__ = fn.prototype;
obj.constructor = fn;
fn.apply(obj, args);
return obj;
}
function Dog(name) {
this.name = name;
}
Dog.prototype.species = 'animal';
var dog = NEW(Dog, '旺財');
console.log(dog.name); // 旺財
複製程式碼
- 如下程式碼,輸出什麼?
function Aoo() {}
function Foo() {}
Foo.prototype = new Aoo();
var foo = new Foo();
console.log(foo instanceof Foo);
console.log(foo instanceof Aoo);
複製程式碼
解釋:instanceof
除了會判斷物件本身的型別,還會判斷物件的 __proto__
的型別,其偽碼大致如下:
function instance_of(L, R) {//L 表示左表示式,R 表示右表示式
var O = R.prototype;// 取 R 的顯示原型
L = L.__proto__;// 取 L 的隱式原型
while (true) {
if (L === null)
return false;
if (O === L)// 這裡重點:當 O 嚴格等於 L 時,返回 true
return true;
L = L.__proto__;
}
}
複製程式碼
答案:true true