早已認為自己已經(jīng)掌握了原型鏈,直到遇到這幾個問題
Object.__proto__ == Object.prototype //false
Object.__proto__ == Function.prototype //true
__proto__倒是經(jīng)常見,但沒有去思考它和prototype的區(qū)別。
概念
對象具有屬性__proto__,可稱為隱式原型,一個對象的隱式原型指向構(gòu)造該對象的構(gòu)造函數(shù)的原型,這也保證了實例能夠訪問到構(gòu)造函數(shù)原型中定義的屬性和方法。
方法(Function)方法這個特殊的對象,除了和其他對象一樣有上述__proto__屬性之外,還有自己特有的屬性——原型屬性(prototype),這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共享的屬性和方法。
new
上面的理論始終離不開構(gòu)造函數(shù)四個字,不如先看看new 干了什么
1.先創(chuàng)建了一個新的空對象
2.然后讓這個空對象的__proto__指向函數(shù)的原型prototype
3.將對象作為函數(shù)的this傳進去,返回創(chuàng)建的這個對象
看到?jīng)],第二步!將對象的__proto__指向函數(shù)的原型prototype。看文字不清楚的話,用代碼模擬下
function New(Foo){
const o = new Object(); //創(chuàng)建了一個新的空對象o
o.__proto__ = Foo.prototype; //讓這個o對象的__proto__指向函數(shù)的原型prototype
Foo.call(o); //this指向o對象
return o;
}
所以很明了了,這些問題再也難不倒你
var a = {};
a.__proto__ == Object.prototype; //a調(diào)用了Object構(gòu)造函數(shù),所以__proto__指向Object.prototype
var b = function(){}
b.__proto__ == Function.prototype //b調(diào)用了Function構(gòu)造函數(shù),所以__proto__指向Function.prototype
b.__proto__.__proto__ == Object.prototype //Function.prototype是個對象,所以它的__proto__指向Object.prototype
Object.__proto__ == Function.prototype //Object作為一個函數(shù)對象,它的__proto__指向構(gòu)造函數(shù)Function的prototype
Object.prototype.__proto__== null //Object.prototype是一切的源頭,所以它的__proto__是null。
但是也有小例外
var obj1 = {a:1};
var obj2 = Object.create(obj1);
obj2.__proto__ == Object.prototype //false
obj2.__proto__ == obj1; //true
這函數(shù)是用現(xiàn)有對象為原型,即__proto__來創(chuàng)建一個新對象。
原型鏈
有如下代碼
function A(){}
A.prototype.c = 1;
var a = new A();
a.c; //1
那么它對應(yīng)的原型鏈

a尋找自己的屬性c沒有找到,就順著__proto__找到了A.prototype,它有屬性c,所以a.c的值是1。
總結(jié)
prototype是函數(shù)才有的屬性,class也可以當作構(gòu)造函數(shù),所以它也有。__proto__是每個對象都有的屬性,它指向該對象的構(gòu)造函數(shù)的prototype。