JS原型鏈

重要的事情說三遍:一切都是對象,一切都是對象廓脆,一切都是對象筛谚!

該文章主要總結了關于js原型鏈的幾個關鍵點,方便自己回憶停忿。

1驾讲、js中對象分為普通對象函數對象

2席赂、凡是通過new Function()創(chuàng)建的都是函數對象吮铭,包括Function自己也是通過new Function()創(chuàng)建的。

3颅停、每個對象(普通對象和函數對象)都有一個__proto__屬性谓晌,prototype屬性只有函數對象有。

4癞揉、原型對象就是一個普通對象纸肉,此普通對象的構造函數是Object。但有例外喊熟,Function.prototype是函數對象柏肪,但他沒有prototype屬性。默認情況下芥牌,任何構造函數.prototype的原型對象都是Object.prototype**

5烦味、每個對象的proto屬性指向自身構造函數的prototype;

例子證明:

var f = function(){};
console.log(typeof Person.prototype);//Object
console.log(typeof Function.prototype);// Function胳泉,這個特殊
console.log(typeof Object.prototype);// Object
console.log(f.prototype.__proto__ ===  Object.prototype);// true
console.log(Function.prototype.__proto__ ===  Object.prototype);// true

總結:原型對象.prototype === undefined拐叉。why? 原型對象是普通對象,普通對象沒有prototype屬性(Function.prototype是個例外扇商,但也可以妥協的這么理解)

5凤瘦、實例并沒有constructor這個屬性,實例通過__proto__屬性找到他的原型對象案铺,此原型對象中有constructor這個屬性蔬芥。

6、原型鏈的實現是通過__proto__實現的控汉。無論是普通對象還是函數對象(我們假設都叫 o)笔诵,要尋找他的原型對象,都是通過o.__proto__去尋找的姑子。

7乎婿、最頂層:Object.prototype.__proto__ === null

測試題:


function Person(name) {

    this.name = name

}

// 修改原型

Person.prototype.getName = function() {};

var p = new Person('jack');

console.log(p.__proto__ === Person.prototype); // true

console.log(p.__proto__ === p.constructor.prototype); // true

解析:

A: JS 在創(chuàng)建對象(不論是普通對象還是函數對象)的時候,都有一個叫做__proto__ 的內置屬性街佑,用于指向創(chuàng)建它的構造函數的原型對象谢翎。

B: p.constructor訪問到p的原型對象(即Person.prototype)中的constructor屬性捍靠,該屬性默認指向Person



function Person(name) {

    this.name = name

}

// 重寫原型

Person.prototype = {

    getName: function() {}

};

var p = new Person('jack');

console.log(p.__proto__ === Person.prototype); // true

console.log(p.__proto__ === p.constructor.prototype); // false

解析:

A:p.constructor訪問到p的原型對象(即Person.prototype)中的constructor屬性森逮,因為重寫了Person.prototype對象榨婆,其構造函數已改變?yōu)?code>Object,即Person.prototype.constructor已指向了Object褒侧。所以p.constructor.prototype === Object.prototype;


進一步:


function Person(name) {

    this.name = name

}

// 重寫原型

Person.prototype = [1];

var p = new Person('jack');

console.log(p.__proto__ === Person.prototype); // true

console.log(p.constructor.prototype === Array.prototype); // true

文章參考為最詳盡的 JS 原型與原型鏈終極詳解良风,沒有「可能是」。文章中有多處錯誤及含糊不清闷供,若有疑問烟央,以本文為主。


不知道為什么歪脏,突然想來個面試題:

    var F = function () {
        var c = 'c';
        this.d = 'd';
        var a = function () {
            console.log('inner a');
        }
    };
    Object.prototype.a = function () {
        console.log('a');
    };
    Function.prototype.b = function () {
        console.log('b');
    };
    var f = new F();
    console.log(f); //請在控制臺查看他的數據結構
    f.a(); // a
    F.a(); // a
    F.b(); // b
    console.log(F.c); //undefined why? 我也不是很懂吊档,但返回undefined還是可以預期的
    console.log(F.d); //undefined why? d綁定到的是this對象,this對象是new出來的唾糯,這個構造函數又不是new它自己出來的
    console.log(f.c); //undefined why? c又沒綁定到this對象,當然訪問不到
    console.log(f.d); //d why? d綁定到了this對象鬼贱,當然訪問的到
    f.b(); // Uncaught TypeError: f.b is not a function

思考為什么執(zhí)行結果是這樣的移怯?
解釋:

  1. f.a(),首先查找自己對象里有沒有a这难?沒有舟误,那好,去f的原型對象中找姻乓。f的原型對象怎么表示嵌溢?f.proto唄,他指向什么蹋岩?對象的構造函數.prototype唄赖草,就是F.prototypeF.prototype的原型對象又是誰呢剪个?也就是F.prototype.proto指向誰呢秧骑?Object.prototype唄。為啥扣囊?引用我上面自己說的那句話:

默認情況下乎折,任何 構造函數.prototype 的原型對象都是 Object.prototype

  1. F.a(),首先查找自己對象里有沒有a侵歇?F方法定義中好像有個定義的a方法骂澄,但是不能訪問啊(原因待續(xù))惕虑,那好吧坟冲,再去F的原型對象中找磨镶。F的原型對象怎么表示?F.proto唄樱衷,他指向什么棋嘲?對象的構造函數.prototype唄(F是個特殊的對象,是函數對象矩桂,它是由Function new出來的沸移,也就是說,它的構造函數是Function)侄榴,就是Funtion.prototype雹锣,Funtion.prototype的原型對象又是誰呢?也就是Funtion.prototype.proto指向誰呢癞蚕?Object.prototype唄蕊爵。

  2. F.b() 請參考上面第二條

  3. f.b() 請參考上面第一條

  4. 擴展閱讀 jQuery原理(附帶部分new的原理),主要看new的部分


新近補充:

prototype 是構造函數的屬性桦山,所以直接設置是 ConstructorFunction.prototype = ......攒射,相當于給類設置原型。
Object.setPrototypeOf() 是給對象設置原型恒水,是為了讓大量 obj.proto = .... 這種寫法更優(yōu)雅会放,有更好的兼容性。
https://segmentfault.com/q/1010000010145735

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末钉凌,一起剝皮案震驚了整個濱河市咧最,隨后出現的幾起案子,更是在濱河造成了極大的恐慌御雕,老刑警劉巖矢沿,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異酸纲,居然都是意外死亡捣鲸,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門福青,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摄狱,“玉大人,你說我怎么就攤上這事无午∶揭郏” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵宪迟,是天一觀的道長酣衷。 經常有香客問我,道長次泽,這世上最難降的妖魔是什么穿仪? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任席爽,我火速辦了婚禮,結果婚禮上啊片,老公的妹妹穿的比我還像新娘只锻。我一直安慰自己,他們只是感情好紫谷,可當我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布齐饮。 她就那樣靜靜地躺著,像睡著了一般笤昨。 火紅的嫁衣襯著肌膚如雪祖驱。 梳的紋絲不亂的頭發(fā)上熙暴,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天啡捶,我揣著相機與錄音,去河邊找鬼拇舀。 笑死崇裁,一個胖子當著我的面吹牛匕坯,可吹牛的內容都是我干的。 我是一名探鬼主播拔稳,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼醒颖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了壳炎?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤逼侦,失蹤者是張志新(化名)和其女友劉穎匿辩,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體榛丢,經...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡铲球,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了晰赞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稼病。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖掖鱼,靈堂內的尸體忽然破棺而出然走,到底是詐尸還是另有隱情,我是刑警寧澤戏挡,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布芍瑞,位于F島的核電站,受9級特大地震影響褐墅,放射性物質發(fā)生泄漏拆檬。R本人自食惡果不足惜洪己,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竟贯。 院中可真熱鬧答捕,春花似錦、人聲如沸屑那。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽齐莲。三九已至痢站,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間选酗,已是汗流浹背阵难。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芒填,地道東北人呜叫。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像殿衰,于是被迫代替她去往敵國和親朱庆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,781評論 2 361