prototype也叫作顯式原型,js里面每個函數(shù)都會有一個prototype屬性攀细,它是一個引用類型,指向的是一個函數(shù)的原型對象。
通過Function.prototype.bind方法構(gòu)造出來的函數(shù)是個例外鹉戚,它沒有prototype屬性。
__proto__叫隱式原型专控,js里面每個對象都會有一個__proto__屬性抹凳,它指向的是創(chuàng)建這個對象的構(gòu)造函數(shù)的prototype。
function A() {
this.a = "a";
this.a_func() = function() {
return this.a;
}
}
console.log(A.prototype);
console.log(A.__proto__);
A.prototype.b = "b";
var a = new A();
console.log(a.b); // b
a.__proto__.c = "c";
console.log(a.c); // c
console.log(a.__proto__ === A.prototype); // true
console.log(A.prototype.constructor === A); // true
執(zhí)行結(jié)果:
解釋:
- A()是一個函數(shù)伦腐,它擁有prototype屬性赢底,它指向一個函數(shù)的原型對象,在你沒有手動指定A.prototype = new xxx()的時候,它默認(rèn)指向的是A的原型對象幸冻,從結(jié)果中看到粹庞,它是一個Object,里面有著function A()的實例可以共享的屬性和方法
- js里面萬物皆對象洽损,F(xiàn)unction是對象庞溜,F(xiàn)unction.prototype也是對象,function A()同樣是對象,它的__proto__指向的是A的構(gòu)造函數(shù)碑定,很明顯它的構(gòu)造函數(shù)是Function()流码,所以A.__proto__ === Function.prototype。
- 當(dāng)實例化了一個A的對象a后延刘,a的__proto__指向的就是它的構(gòu)造函數(shù)A的prototype漫试,故 a.__proto__ === A.prototype。
- 可以在A的原型對象prototype上添加屬性和方法碘赖,這樣所有的A的實例化對象都可以訪問到這個屬性和方法了
- 因為a.__proto__ === A.prototype驾荣,所以在實例a的__proto__上添加屬性和方法是一樣的。
- 從結(jié)果中看到普泡,A.prototype也是一個對象秘车,那么它自然就有一個__proto__屬性,這個__proto__指向的是A.prototype的構(gòu)造函數(shù)Object的prototype(原型對象的構(gòu)造函數(shù)都為Object)劫哼,最后規(guī)定Object.prototype.__proto__ === null
所以叮趴,總的來說,我理解的函數(shù)的prototype就是指向一個對象权烧,這個對象含有這個函數(shù)(可以理解成類)的實例可以共享的屬性和方法眯亦;而__proto__就像一條鏈條,連接著所有的prototype與對象之間的關(guān)系般码,每當(dāng)調(diào)用對象的方法的時候妻率,就會先查找當(dāng)前對象有沒有這個方法,如果沒有板祝,就沿著這條__proto__鏈一直往上找宫静,直到找到Object.prototype.__proto__ == null為止。
一個沿著原型鏈查找屬性方法同時也是js類的繼承的例子:
function A() {
this.a = "showWhere: " + "啊券时,你在A函數(shù)中找到了我孤里!";
this.showWhere = function() {
return this.a;
}
}
A.prototype.xx = "沿著原型鏈自動查找到xx屬性!"
A.prototype.showWhere = function() {
return "showWhere: " + "啊橘洞,你在A.prototype中找到了我捌袜!"
}
function B() {
this.showWhere = function() {
return "showWhere: " + "啊,你在B函數(shù)中找到了我炸枣!";
}
}
B.prototype = new A();
var b = new B();
console.log(b.a);
console.log(b.showWhere()); // 調(diào)用b對象的showWhere方法
console.log(b.__proto__.showWhere()); // 調(diào)用父類A的showWhere方法
console.log(b.__proto__.__proto__.showWhere());// 調(diào)用A.prototype的showWhere方法
console.log(b.xx);
執(zhí)行結(jié)果:
一張圖解釋:
另補(bǔ)充一點虏等,方法和屬性除了顯示地定義在this對象上(this.xxx=)弄唧,默認(rèn)為定義在原型對象prototype上。