[JavaScript] 原型繼承的原理

兩條規(guī)則:

  1. 實(shí)例.__proto__ === 構(gòu)造函數(shù).prototype
  2. 實(shí)例.屬性 === 如果自身有該屬性 ? 實(shí)例.屬性 : 實(shí)例.[__proto__]n次.屬性

關(guān)于規(guī)則2的解釋:
查找實(shí)例的屬性時,先判斷自身有沒有這個屬性,如果有,那么直接獲取。
否則,查找它的__proto__有沒有這個屬性,有的話,就是它,
否則,查找它的__proto__.__proto__有沒有這個屬性……
如果一直找不到,就是undefined。(此處必有蹊蹺……略

測試用例:(測試環(huán)境,Chrome 44,Win7)

1. 考察構(gòu)造函數(shù)和實(shí)例

var F=function(){};    //構(gòu)造函數(shù)F
F.prototype={};    //先設(shè)置構(gòu)造函數(shù)的prototype
var f=new F;    //造一個實(shí)例
console.assert(f.__proto__===F.prototype);    //根據(jù)規(guī)則1

console.assert(f.a===undefined);    //實(shí)例還沒有這個屬性

F.prototype.a=1;    //給prototype增加一個屬性
console.assert(f.a===f.__proto__.a);    //根據(jù)規(guī)則2
console.assert(f.a===F.prototype.a);    //根據(jù)規(guī)則1
console.assert(f.a===1);    //找到了屬性值

總結(jié):

f.a===f.__proto__.a
===F.prototype.a===1

2. 考察繼承

var G=function(){};    //再來一個構(gòu)造函數(shù)
G.prototype=f;    //讓這個構(gòu)造函數(shù)的prototype是剛才那個實(shí)例
var g=new G;    //再造一個實(shí)例
console.assert(g.__proto__===G.prototype);    //根據(jù)規(guī)則1

console.assert(g.__proto__===f);    //根據(jù)剛才的賦值
console.assert(g.a===g.__proto__.a);    //根據(jù)規(guī)則2
console.assert(g.a===f.a);    //根據(jù)上面的推導(dǎo)
console.assert(g.a===1);    //找到了屬性值

總結(jié):

g.a===g.__proto__.a===g.__proto__.__proto__.a
===G.prototype.__proto__.a===f.__proto__.a===F.prototype.a===1

3. 考察只讀性

g.a=2;    //為實(shí)例增加屬于自己的屬性
console.assert(g.a===2);    //根據(jù)規(guī)則2
console.assert(f.a===1);    //不影響其他實(shí)例的查找規(guī)則

結(jié)論:
原型繼承,本質(zhì)上利用了實(shí)例屬性的查找規(guī)則。

參考文獻(xiàn):
《ECMAScript? 2015 Language Specification》——第3頁 4.2.1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容