成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

繼承的那些事

CoyPan / 1478人閱讀

摘要:借用構(gòu)造函數(shù)繼承針對(duì)上面的繼承方法的缺點(diǎn),開(kāi)發(fā)人員使用一種叫做借用構(gòu)造函數(shù)的技術(shù),也就是我們平時(shí)說(shuō)的跟繼承。

繼承是 OO 語(yǔ)言中一個(gè)最為津津樂(lè)道的概念,許多 OO 語(yǔ)言都支持兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。由于函數(shù)沒(méi)有簽名,在 ECMAScript 中無(wú)法實(shí)現(xiàn)接口繼承。ECMAScript 只支持實(shí)現(xiàn)繼承而且實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)實(shí)現(xiàn)的。

關(guān)于原型鏈,我之前的文章里面有介紹,如果有些忘記了,可以看這篇文章。
下面我將詳細(xì)的介紹前端前輩在開(kāi)發(fā)過(guò)程中不斷摸索創(chuàng)造的幾種繼承方式。看完面試的時(shí)候千萬(wàn)不要簡(jiǎn)單的回答 call 跟 apply 了。
為了說(shuō)起來(lái)省事,雖然 js 沒(méi)有嚴(yán)格意義的類(lèi),我還是以父類(lèi)和子類(lèi)來(lái)做區(qū)分繼承關(guān)系。

1. prototype模式繼承

既然子類(lèi)想要繼承父類(lèi)的全部方法,而且我們知道父類(lèi)的實(shí)例擁有父類(lèi)所有的方法,那么接下類(lèi)就好辦了,我將子類(lèi)的 prototype 指向父類(lèi)的實(shí)例,子類(lèi)就擁有了父類(lèi)的全部方法了

// 定義父類(lèi)
function Parent (name, age) {
    this.name = name;
    this.age = age;
}
Parent.prototype.sayName = function () {
    alert(this.name);
}
// 定義子類(lèi)
function Child (sex) {
    this.sex = sex;
}
// 實(shí)現(xiàn)繼承
var p = new Parent("leizore", 25);
Child.prototype = p;
var child = new Child("男");
child.sayName();            // leizore

那么對(duì)應(yīng)的關(guān)系圖如下:

這種方式 Child 繼承了 Person 的全部方法,但是也是有缺點(diǎn)的。

創(chuàng)建子類(lèi)實(shí)例時(shí),無(wú)法向父類(lèi)構(gòu)造函數(shù)傳參。指定 prototype 時(shí),實(shí)例化 Person 傳的參數(shù),會(huì)出現(xiàn)在所有子類(lèi)上,不靈活。

由圖可以看到,p 的 contructor 指向 Person, 所以 Child.prototype.constructor 也指向 Person,顯然會(huì)導(dǎo)致繼承鏈的紊亂。

2.借用構(gòu)造函數(shù)繼承

針對(duì)上面的繼承方法的缺點(diǎn)1,開(kāi)發(fā)人員使用一種叫做借用構(gòu)造函數(shù)的技術(shù),也就是我們平時(shí)說(shuō)的 call 跟 apply 繼承。

// 定義父類(lèi)
function Parent (name, age) {
    this.name = name;
    this.age = age;
}
Parent.prototype.sayName = function () {
    alert(this.name);
}
// 定義子類(lèi)
function Child (name, age, sex) {
     // 繼承,同時(shí)傳遞了參數(shù)
    Parent.call(this, name, age)
    this.sex = sex;
}

這里簡(jiǎn)單講一下 call(apply)是如何實(shí)現(xiàn)的,其實(shí)就是將 call(apply) 前面的函數(shù)立即執(zhí)行一遍,并且執(zhí)行時(shí)將作用域 this 指向 call(apply) 函數(shù)的第一個(gè)參數(shù),比如這里的 call 就是將 Parent 實(shí)例一遍,將 name 跟 age 當(dāng)成參數(shù)傳過(guò)去
這種繼承方式解決了繼承過(guò)程中的傳參問(wèn)題,但是缺點(diǎn)是并沒(méi)有繼承到父類(lèi)的原型,為了解決這個(gè)問(wèn)題,我們很容易想到將上面兩個(gè)方法結(jié)合起來(lái)不久好了。于是另一種繼承方式出現(xiàn)了

3.組合繼承

沒(méi)錯(cuò),就是兩種方式并用,從而發(fā)揮兩者之長(zhǎng)的一種繼承模式,代碼如下

// 定義父類(lèi)
function Parent (name, age) {
    this.name = name;
    this.age = age;
}
Parent.prototype.sayName = function () {
    alert(this.name);
}
// 定義子類(lèi)
function Child (name, age, sex) {
    // 繼承,同時(shí)傳遞了參數(shù)
    Parent.call(this, name, age)
    this.sex = sex;
}
Child.prototype = new Parent("leizore", 25);

嗯,這種方式基本上解決了開(kāi)發(fā)過(guò)程中繼承的痛點(diǎn),成為好多人常用的繼承模式之一。但是缺點(diǎn)也是有的

重復(fù)定義了屬性,可以看到將 Child 的 prototype指向 Perent 的實(shí)例時(shí),繼承了name 跟 age 屬性,實(shí)例 Child 的時(shí)候,調(diào)用 call 函數(shù),又繼承了一次,雖然使用 call 調(diào)用這次的屬性是在實(shí)例屬性上,當(dāng)獲取name時(shí)優(yōu)先返回實(shí)例屬性,然后在 prototype 上,所以并不會(huì)出大問(wèn)題。

第一種繼承方式方式的缺點(diǎn)二也完美的繼承過(guò)來(lái)了,Child.prototype.constructor 還是指向 parent

那么肯定有人會(huì)說(shuō),既然Child.prototype.constructor 不指向自己,那么直接讓他指向自己不就好了?

Child.prototype.constructor = Child;

答案是不行的。因?yàn)?Child.prototype 是 Parent 的實(shí)例,這樣操作會(huì)將 Parent.prototype.constructor 也指向 Child,顯然也是不合理的。

4.原型式繼承

為了解決上面 Child 與 Parent 繼承之后糾纏不清的問(wèn)題,道格拉斯在2006年提出一種繼承方法,它的想法是借助原型可以給予已有的對(duì)象創(chuàng)建新對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類(lèi)型。函數(shù)如下

function object (o) {
    function F() {}
    F.prototype = o;
    return new F();
}

這個(gè)模式相當(dāng)與創(chuàng)建一個(gè)新的對(duì)象,對(duì)象繼承了o所有屬性,當(dāng)然這里也只是實(shí)現(xiàn)了淺拷貝。

5.組合寄生式繼承

嗯,想必大家也想到了,上面這種繼承方式可以解決 Child 與 Parent 繼承后的糾纏不清的關(guān)系??梢杂?object 方法創(chuàng)建一個(gè)臨時(shí)對(duì)象,從而斬?cái)喔?Parent 的聯(lián)系。就可以放心的對(duì) Child 原型的constructor 隨便指了,當(dāng)然了為了繼承鏈的不紊亂,還是指向自己比較好

// 定義父類(lèi)
function Parent (name, age) {
    this.name = name;
    this.age = age;
}
Parent.prototype.sayName = function () {
    alert(this.name);
}
// 定義子類(lèi)
function Child (name, age, sex) {
    // 繼承,同時(shí)傳遞了參數(shù)
    Parent.call(this, name, age)
    this.sex = sex;
}
function object (o) {
    function F() {}
    F.prototype = o;
    return new F();
}
var prototype = object(Parent.prototype);
prototype.constructor = Child;
Child.prototype = prototype;


var c = new Child("leizore", 11, "men");
c.sayName()                // leizore
c.constructor === Child    // true

到此,基本上解決了上面所說(shuō)的所有缺點(diǎn)。當(dāng)然了,也是有一點(diǎn)問(wèn)題的,就是方法四的實(shí)現(xiàn)其實(shí)是淺拷貝,如果 Parent.prototype 里又引用類(lèi)型比如數(shù)組,對(duì)象,改變Parent.prototype,Child 也會(huì)跟著變,解決方式也很簡(jiǎn)單,使用深拷貝就行了,同時(shí)又可以寫(xiě)很多繼承方式。當(dāng)然了,按照我上面順下來(lái)的思想,也可以寫(xiě)出自己的繼承方式
比如下面改變object函數(shù):

// 定義父類(lèi)
function Parent (name, age) {
    this.name = name;
    this.age = age;
}
Parent.prototype.sayName = function () {
    alert(this.name);
}
// 定義子類(lèi)
function Child (name, age, sex) {
    // 繼承,同時(shí)傳遞了參數(shù)
    Parent.call(this, name, age)
    this.sex = sex;
}
function object (o) {
    var c = {};
   for (var i in o) {
     c[i] = o[i];
   }
   return c
}
var prototype = object(Parent.prototype);
prototype.constructor = Child;
Child.prototype = prototype;


var c = new Child("leizore", 11, "men");
c.sayName()                // leizore
c.constructor === Child    // true

當(dāng)然了,es6 中,可以通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承,這里就不多說(shuō)了

參考

javascript 高級(jí)程序設(shè)計(jì)

Javascript面向?qū)ο缶幊蹋ǘ簶?gòu)造函數(shù)的繼承

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/95660.html

相關(guān)文章

  • JavaScript 繼承那些

    摘要:實(shí)際上也就是在原型鏈繼承的代碼中添加在子類(lèi)的構(gòu)造函數(shù)中調(diào)用父類(lèi)構(gòu)造函數(shù)。寄生組合式繼承在指定子類(lèi)的原型的時(shí)候不必調(diào)用父類(lèi)的構(gòu)造函數(shù),而是直接使用創(chuàng)建父類(lèi)原型的副本。 原本地址:http://www.ahonn.me/2017/01/2... 眾所周知,JavaScript 的繼承是實(shí)現(xiàn)繼承,而沒(méi)有 Java 中的接口繼承。這是因?yàn)?JavaScript 中函數(shù)沒(méi)有簽名,而實(shí)現(xiàn)繼承依靠的...

    singerye 評(píng)論0 收藏0
  • 【面試】Java基礎(chǔ)那些-Two

    摘要:前言面試中對(duì)于技術(shù)職位,一般分筆試與面談,如果面試官的一些小問(wèn)題你可以立馬找到對(duì)應(yīng)的知識(shí)點(diǎn)擴(kuò)展開(kāi)來(lái),那么這就是你的優(yōu)勢(shì),本系列將講述一些面試中的事,不會(huì)很詳細(xì),但是應(yīng)該比較全面吧。 前言 面試中對(duì)于技術(shù)職位,一般分筆試與面談,如果面試官的一些小問(wèn)題你可以立馬找到對(duì)應(yīng)的知識(shí)點(diǎn)擴(kuò)展開(kāi)來(lái),那么這就是你的優(yōu)勢(shì),本系列將講述一些java面試中的事,不會(huì)很詳細(xì),但是應(yīng)該比較全面吧。 主要內(nèi)容 pa...

    you_De 評(píng)論0 收藏0
  • js面向?qū)ο鬁\析--繼承那些

    摘要:有需要還可以修改指向謙龍寄生組合式繼承思路是通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性,通過(guò)原型鏈的混合形式來(lái)繼承方法改變執(zhí)行環(huán)境實(shí)現(xiàn)繼承有需要還可以修改指向謙龍謙龍拷貝繼承該方法思路是將另外一個(gè)對(duì)象的屬性和方法拷貝至另一個(gè)對(duì)象使用遞歸 前言 js中實(shí)現(xiàn)繼承的方式只支持實(shí)現(xiàn)繼承,即繼承實(shí)際的方法,而實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)完成的。 原型鏈?zhǔn)嚼^承 該方式實(shí)現(xiàn)的本質(zhì)是重寫(xiě)原型對(duì)象,代之以一個(gè)新類(lèi)型的實(shí)例...

    molyzzx 評(píng)論0 收藏0
  • 關(guān)于繼承那些

    摘要:格式子類(lèi)名父類(lèi)名好處提高了代碼的復(fù)用性提高了代碼的維護(hù)性通過(guò)少量的修改,滿(mǎn)足不斷變化的具體要求讓類(lèi)與類(lèi)產(chǎn)生了一個(gè)關(guān)系,是多態(tài)的前提要求有共同的屬性或操作有細(xì)微的差別繼承的弊端讓類(lèi)的耦合性增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000019321816?w=600&h=242); 第二階段 JAVA面向?qū)ο?第二章 繼承 其...

    soasme 評(píng)論0 收藏0
  • 【JS基礎(chǔ)】原型對(duì)象那些(一)

    摘要:通過(guò)同一個(gè)構(gòu)造函數(shù)實(shí)例化的多個(gè)實(shí)例對(duì)象具有同一個(gè)原型對(duì)象。所以當(dāng)給原型對(duì)象賦值一個(gè)新對(duì)象時(shí),切記將原型對(duì)象的指回原構(gòu)造函數(shù)以上就是本次分享的內(nèi)容,關(guān)于原型對(duì)象的其他知識(shí),下一篇基礎(chǔ)原型對(duì)象的那些事二會(huì)講到。 談起js的基礎(chǔ),繞不過(guò)去的坎就是:原型鏈、作用域鏈、this(em...好吧,還有閉包),今天總結(jié)一下關(guān)于原型對(duì)象的一些知識(shí),供自己和大家復(fù)習(xí)。 概念理解 什么是原型對(duì)象呢?有以下...

    edgardeng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<