原型和繼承 -- 總結(jié)

原型模式

原型模式在《JavaScript高級程序設(shè)計》中的定義:

我們創(chuàng)建的每個函數(shù)都有一個prototype(原型)屬性若债,這個屬性是一個指針,指向一個對象精绎,而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法递宅。如果按照字面意思來理解,那么prototype就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個對象實例的原型對象萝勤。使用這個對象的好處就是可以讓所有對象實例共享它包含的屬性和方法。

這里還有一個__proto__屬性呐伞,每一個對象都擁有這個屬性敌卓,這個屬性指向?qū)?yīng)的構(gòu)造函數(shù)的prototype屬性。

通過原型對象伶氢,我們就不用將信息添加到構(gòu)造函數(shù)中了趟径。

實例對象共享原型對象的屬性

function Person(){}
Person.prototype.name = 'A'
Person.prototype.age = 1
// 實例對象共享原型對象的屬性
let p1 = new Person()
console.log(p1.name, p1.age);   // A 1
let p2 = new Person()
console.log(p2.name, p2.age);   // A 1

constructor(構(gòu)造函數(shù))屬性

每個原型對象在默認(rèn)情況下都會自動獲取一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指針癣防,指向這個原型所在的函數(shù)蜗巧。在上面的例子中,創(chuàng)建Person函數(shù)后蕾盯,它的prototype指向它的原型對象幕屹,這個原型對象就會獲取獲取constructor屬性,指向Person函數(shù)。

判斷實例對象與原型對象之間的關(guān)系

  • Obj.prototype.isPrototypeOf(obj)
console.log(Person.prototype.isPrototypeOf(p1)) // true
  • Object.getPrototypeOf(obj):返回對象實例的原型[es5]
console.log(Object.getPrototypeOf(p1) == Person.prototype);   // true
console.log(Object.getPrototypeOf(p1).name);    // A
  • obj.hasOwnPrototype(attr):檢測一個屬性是否存在于實例中望拖。只有當(dāng)實例對象重寫原型對象的屬性后(非原型屬性)才會返回true渺尘。
console.log(p1.hasOwnProperty('name')); // false
p1.name = 'Ertsul'
console.log(p1.hasOwnProperty('name')); //true
  • in操作符:通過in操作符和hasOwnProperty()可以判斷某屬性存在于實例還是原型對象中【in判斷是否存在屬性,hasOwnProperty()判斷存在于哪里说敏∨父】可以單獨使用和for-in循環(huán)使用:無論屬性屬于實例還是原型中,都會返回true盔沫。(‘name’ in person1)

  • 獲取所有實例的屬性名字锌雀,無論是否可以枚舉。

console.log(Object.getOwnPropertyNames(p1)); // ["name"]
  • instanceof
console.log(p1 instanceof Person);    // true

更簡單的語法

function Person() {  }
Person.prototype = {
 name: '001'
}
let p1 = new Person()
console.log(p1.name);

這里的例外是:constructor屬性不再指向Person迅诬;本質(zhì)上相當(dāng)于完全重寫了Person對象了腋逆。注:重寫原型對象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對象實例之間的聯(lián)系,它們引用的仍然是最初的原型侈贷。[詳見《JavaScript高級程序設(shè)計》P156-P157惩歉,原型的動態(tài)性]

搜索機制

  • 解釋器會現(xiàn)在目標(biāo)對象中搜索目標(biāo)屬性,如果當(dāng)前對象沒有目標(biāo)屬性俏蛮,解釋器繼續(xù)在目標(biāo)對象的原型對象中搜索撑蚌。
  • 通過delete只能刪除對象的屬性,而不能刪除原型對象中的屬性搏屑。

組合模式(默認(rèn)類型):構(gòu)造函數(shù)模式 + 原型模式

構(gòu)造函數(shù)模式用于定義實例屬性争涌,而原型模式用于定義方法和共享的屬性。

繼承

原型鏈

// 父親
function Father() { 
 this.fatherProperty = true
}
Father.prototype.getFatherValue = function () { 
 return this.fatherProperty
}
// 兒子
function Son() { 
 this.sonProperty = false
}
// 繼承父親:通過實例化父親辣恋,將實例化對象作為兒子的原型亮垫,這樣兒子就繼承了父親的屬性
Son.prototype = new Father()
Son.prototype.getSonValue = function () { 
 return this.sonProperty
}

let instance = new Son()
console.log(instance.fatherProperty);   // true

上面例子中,通過實例化父親伟骨,將實例化對象作為兒子的原型饮潦,這樣兒子就繼承了父親的屬性。(重寫兒子的原型)携狭。這里继蜡,兒子原型對象的[[prototype]](注:不是prototype,[[prototype]]存在于原型中)指向的是父親的原型對象逛腿,而父親的原型對象的[[prototype]]指向的是Object Prototype稀并。(由于所有函數(shù)的默認(rèn)原型都是Object的實例,所以默認(rèn)原型都會包含一個內(nèi)部指針单默,指向Object.prototype)

借用構(gòu)造函數(shù)

  • 主要是為了解決因為引用類型值的原型屬性會被所有實例共享的問題碘举。
  • 借用構(gòu)造函數(shù)/偽造對象/經(jīng)典繼承:在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。
// 父親
    function Father() { 
     this.info = ['Zero']
    }
    // 兒子
    function Son() { 
     // 繼承父親:在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)
     // 《JavaScript高級程序設(shè)計》:函數(shù)只不過是在特定環(huán)境中執(zhí)行代碼的對象雕凹,因此通過使用 apply()和 call() 可以在新創(chuàng)建的對象上執(zhí)行構(gòu)造函數(shù)殴俱。 
     Father.call(this)        // 借用超類的構(gòu)造函數(shù)
    }

    let f = new Father()
    f.info.push('100')
    console.log(f.info);    // ["Zero", "100"]

    let s = new Son()
    console.log(s.info);    // ["Zero"]

如果在繼承的時候要傳遞參數(shù),則在后面添加參數(shù)即可枚抵。如:Father.call(this线欲, param1, param2)

__proto__

通過__proto__也可以實現(xiàn)子類型對超類型的繼承。

const obj = {
 num : 123 
}
const obj1 = {
 __proto__ : obj
}
console.log(obj1.num);  // 123

Object.create(source)

const obj = {
 num : 123 
}
const obj2 = Object.create(obj)
console.log(obj2.num);  // 123

Object.assign(Object.create(obj), {…})

const obj = {
 num : 123 
}
const obj3 = Object.assign(
 Object.create(obj),
 {
 num2 : 234
 }
)
console.log(obj3.num, obj3.num2);   // 123 234

補充

繼承機制如下圖:

image.png

測試代碼如下:

// 父類
function SuperType(){
}
// 子類
function SubType(){

}
// 子類繼承父類
SubType.prototype = new SuperType();
// 實例化父類和子類
let superIns = new SuperType();
let subIns = new SubType();

// 子類
console.log(SubType.prototype);     // SuperType {}
console.log(subIns.__proto__);      // SuperType {}

// 父類
console.log(SuperType.prototype);       // {constructor: ?} 
console.log(superIns.__proto__);        // {constructor: ?}

console.log(SuperType.prototype.__proto__);     
// {constructor: ?, __defineGetter__: ?, __defineSetter__: ?, hasOwnProperty: ?, __lookupGetter__: ?, …}
// 即: Object prototype

console.log(SuperType.prototype.__proto__.constructor);
// ? Object() { [native code] } 即:Object
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汽摹,一起剝皮案震驚了整個濱河市李丰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逼泣,老刑警劉巖趴泌,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拉庶,居然都是意外死亡嗜憔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門氏仗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吉捶,“玉大人,你說我怎么就攤上這事皆尔∧盘颍” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵慷蠕,是天一觀的道長珊拼。 經(jīng)常有香客問我,道長流炕,這世上最難降的妖魔是什么澎现? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮每辟,結(jié)果婚禮上昔头,老公的妹妹穿的比我還像新娘。我一直安慰自己影兽,他們只是感情好揭斧,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著峻堰,像睡著了一般讹开。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捐名,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天旦万,我揣著相機與錄音,去河邊找鬼镶蹋。 笑死成艘,一個胖子當(dāng)著我的面吹牛赏半,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淆两,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼断箫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秋冰?” 一聲冷哼從身側(cè)響起仲义,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剑勾,沒想到半個月后埃撵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡虽另,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年暂刘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捂刺。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸳惯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叠萍,到底是詐尸還是另有隱情芝发,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布苛谷,位于F島的核電站辅鲸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腹殿。R本人自食惡果不足惜独悴,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锣尉。 院中可真熱鬧刻炒,春花似錦、人聲如沸自沧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拇厢。三九已至爱谁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孝偎,已是汗流浹背访敌。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衣盾,地道東北人寺旺。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓爷抓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阻塑。 傳聞我的和親對象是個殘疾皇子蓝撇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容