成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript中的繼承

guyan0319 / 716人閱讀

摘要:前言作為中最重要的內(nèi)容之一,繼承問題一直是我們關(guān)注的重點。如果一個類別繼承自另一個類別,就把這個稱為的子類,而把稱為的父類別也可以稱是的超類。

前言

作為 JavaScript 中最重要的內(nèi)容之一,繼承問題一直是我們關(guān)注的重點。那么你是否清晰地知道它的原理以及各種實現(xiàn)方式呢

閱讀這篇文章,你將知道:

什么是繼承

實現(xiàn)繼承有哪幾種方式

它們各有什么特點

這里默認你已經(jīng)清楚的知道構(gòu)造函數(shù)、實例和原型對象之間的關(guān)系,如果并不是那么清晰,那么推薦你先閱讀這篇文章 -- JavaScript 中的原型與原型鏈

如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過

以下↓

概念
繼承(inheritance)是面向?qū)ο筌浖夹g(shù)當中的一個概念。如果一個類別 B 繼承自 另一個類別 A ,就把這個 B 稱為 A的子類 ,而把 A 稱為 B的父類別 也可以稱 A是B的超類 。繼承可以使得子類具有父類別的各種屬性和方法,而不需要再次編寫相同的代碼 ...更多)

通過這些概念和圖示我們不難知道繼承可以在我們的開發(fā)中帶來的便捷,那么在 JavaScript 中如何去實現(xiàn)繼承呢?

繼承實現(xiàn)方式 原型鏈繼承
利用原型讓一個引用類型繼承另一個引用類型的屬性和方法
function SuperType() {
    this.name = "tt";
}
SuperType.prototype.sayName = function() {
    return this.name
}

function SubType() {
    this.name = "oo";
}
SubType.prototype = new SuperType()

var instance = new SubType()

instance.sayName() // oo
instance instanceof SubType // true
instance instanceof SuperType // ture

以上的試驗中,我們創(chuàng)建了兩個構(gòu)造函數(shù) SuperTypeSubType ,并且讓 SubType 的原型指向 SuperType ,SubType 也就繼承了 SuperType 原型對象中的方法。所以在創(chuàng)建 instance 實例的時候,實例本身也就具有了 SuperType 中的方法,并且都處在它們的原型鏈中

SubType.prototype.constructor == SubType // false
SubType.prototype.constructor == SuperType // true

需要注意的是:這個時候 SubType.prototype.constructor 是指向 SuperType 的,相當于重寫了 SubType 的原型對象。

用一張圖表示:

SubType.prototype 相當于 SuperType 的實例存在的,所以 SubType.prototype.constructor 就指向 SuperType

原型繼承的特點

優(yōu)點:

簡單、易于實現(xiàn)

父類新增原型方法/原型屬性,子類都能訪問到

非常純粹的繼承關(guān)系,實例是子類的實例,也是父類的實例

缺點:

無法實現(xiàn)多繼承

想要為子類 SubType 添加原型方法,就必須在 new SuperType 之后添加(會覆蓋)

來自原型對象的所有屬性被所有實例共享(引用類型的值修改會反映在所有實例上面)

創(chuàng)建子類實例時,無法向父類構(gòu)造函數(shù)傳參

借用構(gòu)造函數(shù)
在子類構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),通過 applycall 實現(xiàn)
function SuperType(name) {
    this.name = name;
    this.colors = ["red", "orange", "black"];
}

function SubType() {
    SuperType.call(this, "tt");
}

var instance = new SubType()
var instance1 = new SubType()

instance.colors // ["red", "orange", "black"]
instance.name // tt

instance.colors.push("green");
instance.colors // ["red", "orange", "black", "green"]
instance1.colors // ["red", "orange", "black"]
借用構(gòu)造函數(shù)的特點

優(yōu)點:

解決了原型鏈繼承不能傳參的問題

子類實例共享父類引用屬性的問題

可以實現(xiàn)多繼承(call可以指定不同的超類)

缺點:

實例并不是父類的實例,只是子類的實例

只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法

無法實現(xiàn)函數(shù)復用

組合繼承
偽經(jīng)典繼承(最常用的繼承模式):將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一起。使用原型鏈實現(xiàn)對原型屬性和方法的繼承,通過構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承
function SuperType(name) {
    this.name = name;
    this.colors = ["red", "orange", "black"];
}
SuperType.prototype.sayName = function() {
    return this.name
}

function SubType() {
    SuperType.call(this, "tt");
    this.name = "oo";
}
// 這里的 SubType.prototype.constructor 還是指向 SuperType
SubType.prototype = new SuperType();

var instance = new SubType();
var instance1 = new SubType();

instance.name // oo
instance.sayName() // oo

instance.colors.push("green");
instance.colors // ["red", "orange", "black", "green"]
instance1.colors // ["red", "orange", "black"]
組合繼承的特點

優(yōu)點:

可以繼承實例屬性/方法,也可以繼承原型屬性/方法

不存在引用屬性共享問題

可傳參

函數(shù)可復用

缺點:

調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實例(子類實例將子類原型上的那份屏蔽了)

原型式繼承
借助原型鏈可以基于已有的對象創(chuàng)建新對象,同時還不必因此創(chuàng)建自定義類型
function obj(o) {
    function F(){}
    F.prototype = o;
    return new F();
}

var person = {
    name: "tt",
    age: 18,
    colors: ["red", "green"]
}

var instance = obj(person);
var instance1 = obj(person);
instance.colors.push("black");
instance.name // tt
instance.colors // ["red", "green", "black"]
instance1.colors // ["red", "green", "black"]

創(chuàng)建一個臨時的構(gòu)造函數(shù),然后將傳入的對象當做這個構(gòu)造函數(shù)的原型對象,最后返回這個臨時構(gòu)造函數(shù)的新實例。實際上,就是對傳入的對象進行了一次淺復制

ES5 通過新增 Object.create() 規(guī)范化了原型式繼承

更多 Object.create()語法請點擊 這里

原型式繼承特點

優(yōu)點:

支持多繼承(傳入的對象不同)

不需要興師動眾的創(chuàng)建很多構(gòu)造函數(shù)

缺點: 和原型鏈繼承基本一致,效率較低,內(nèi)存占用高(因為要拷貝父類的屬性)

寄生式繼承
創(chuàng)建一個僅用于封裝繼承過程的函數(shù),在函數(shù)內(nèi)部對這個對象進行改變,最后返回這個對象
function createAnother(obj) {
    var clone = Object(obj);
    clone.sayHi = function() {
        alert("Hi");
    }
    return clone
}

var person = {
    name: "tt",
    age: 18,
    friends: ["oo", "aa", "cc"],
    sayName() {
        return this.name
    }
}

var instance = createAnother(person)
var instance1 = createAnother(person)

instance.friends.push("yy")

instance.name // "tt"
instance.sayHi() // Hi
instance.friends // ["oo", "aa", "cc", "yy"]
instance1.friends // ["oo", "aa", "cc", "yy"]
寄生式繼承的特點

優(yōu)點:

支持多繼承

缺點:

實例并不是父類的實例,只是子類的實例

不能實現(xiàn)復用(與構(gòu)造函數(shù)相似)

實例之間會互相影響

寄生組合繼承
借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。通過寄生方式,砍掉父類的實例屬性,這樣,在調(diào)用兩次父類的構(gòu)造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
function inherit(subType, superType) {
    var obj = Object(superType.prototype); // 創(chuàng)建對象
    obj.constructor = subType;  // 指定constructor
    subType.prototype = obj;    // 指定對象
}

function SuperType(name) {
    this.name = name;
    this.colors = ["red", "orange", "black"];
}
SuperType.prototype.sayName = function() {
    return this.name
}

function SubType() {
    SuperType.call(this, "tt");
    this.name = "oo";
}

inherit(SubType, SuperType)

var instance = new SubType()

instance.name // oo
instance.sayName // oo
instance instanceof SubType // true
instance instanceof SuperType // true
SubType.prototype.constructor == SubType // true
寄生組合繼承的特點

堪稱完美,只是實現(xiàn)稍微復雜一點

后記

作為 JavaScript 最重要的概念之一,對于繼承實現(xiàn)的方式方法以及它們之間的差異我們還是很有必要了解的。

在實現(xiàn)繼承的時候,拷貝 也是一種很有效的方式,由于 JavaScript 簡單數(shù)據(jù)類型與引用類型的存在,衍生出了 淺拷貝深拷貝 的概念,那么它們又是什么,怎么去實現(xiàn)呢

且聽下回分解,哈哈

周末愉快

最后,推薦一波前端學習歷程,不定期分享一些前端問題和有意思的東西歡迎 star 關(guān)注 傳送門

參考文檔

JavaScript 高級程序設計

JavaScript實現(xiàn)繼承的幾種方式

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103697.html

相關(guān)文章

  • 徹底搞懂JavaScript中的繼承

    摘要:這正是我們想要的太棒了毫不意外的,這種繼承的方式被稱為構(gòu)造函數(shù)繼承,在中是一種關(guān)鍵的實現(xiàn)的繼承方法,相信你已經(jīng)很好的掌握了。 你應該知道,JavaScript是一門基于原型鏈的語言,而我們今天的主題 -- 繼承就和原型鏈這一概念息息相關(guān)。甚至可以說,所謂的原型鏈就是一條繼承鏈。有些困惑了嗎?接著看下去吧。 一、構(gòu)造函數(shù),原型屬性與實例對象 要搞清楚如何在JavaScript中實現(xiàn)繼承,...

    _ivan 評論0 收藏0
  • Javascript 設計模式讀書筆記(三)——繼承

    摘要:的繼承方式屬于原型式繼承,非常靈活。當使用關(guān)鍵字執(zhí)行類的構(gòu)造函數(shù)時,系統(tǒng)首先創(chuàng)建一個新對象,這個對象會繼承自構(gòu)造函數(shù)的原型對象新對象的原型就是構(gòu)造函數(shù)的屬性。也就是說,構(gòu)造函數(shù)用來對生成的新對象進行一些處理,使這個新對象具有某些特定的屬性。 繼承這個東西在Javascript中尤其復雜,我掌握得也不好,找工作面試的時候在這個問題上栽過跟頭。Javascript的繼承方式屬于原型式繼承,...

    cangck_X 評論0 收藏0
  • javascript繼承你了解多少?

    摘要:和構(gòu)造函數(shù)前面提到,是個內(nèi)置隱藏屬性,雖然在可以通過訪問,但是其設計本意是不可被讀取和修改的,那么我們?nèi)绾卫迷玩渷斫⒗^承關(guān)系提供了關(guān)鍵字。到這兒,思路就清晰了,怎么讓對象和對象的相連實現(xiàn)繼承只需把的構(gòu)造函數(shù)的連接到就行了。 什么是繼承? 大多數(shù)人使用繼承不外乎是為了獲得這兩點好處,代碼的抽象和代碼的復用。代碼的抽象就不用說了,交通工具和汽車這類的例子數(shù)不勝數(shù),在傳統(tǒng)的OO語言中(...

    baishancloud 評論0 收藏0
  • 白話解釋 Javascript 原型繼承(prototype inheritance)

    摘要:我們有了構(gòu)造函數(shù)之后,第二步開始使用它構(gòu)造一個函數(shù)。來個例子這種方式很簡單也很直接,你在構(gòu)造函數(shù)的原型上定義方法,那么用該構(gòu)造函數(shù)實例化出來的對象都可以通過原型繼承鏈訪問到定義在構(gòu)造函數(shù)原型上的方法。 來源: 個人博客 白話解釋 Javascript 原型繼承(prototype inheritance) 什么是繼承? 學過面向?qū)ο蟮耐瑢W們是否還記得,老師整天掛在嘴邊的面向?qū)ο笕筇?..

    kid143 評論0 收藏0
  • [譯] 為什么原型繼承很重要

    摘要:使用構(gòu)造函數(shù)的原型繼承相比使用原型的原型繼承更加復雜,我們先看看使用原型的原型繼承上面的代碼很容易理解。相反的,使用構(gòu)造函數(shù)的原型繼承像下面這樣當然,構(gòu)造函數(shù)的方式更簡單。 五天之前我寫了一個關(guān)于ES6標準中Class的文章。在里面我介紹了如何用現(xiàn)有的Javascript來模擬類并且介紹了ES6中類的用法,其實它只是一個語法糖。感謝Om Shakar以及Javascript Room中...

    xiao7cn 評論0 收藏0

發(fā)表評論

0條評論

guyan0319

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<