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

資訊專欄INFORMATION COLUMN

Javascript的對象繼承方法

cloud / 1797人閱讀

摘要:創(chuàng)建實(shí)例時(shí)無法向的構(gòu)造函數(shù)傳遞參數(shù)在不影響所有對象實(shí)例的情況下易錯(cuò)點(diǎn)添加原型方法的代碼要放在替換原型的語句之后。繼承屬性繼承方法原型式繼承原型式繼承并沒有使用嚴(yán)格意義上的構(gòu)造函數(shù)。

許多OO 語言都支持兩種繼承方式:

接口繼承:只繼承方法簽名

實(shí)現(xiàn)繼承:繼承實(shí)際的方法。

由于函數(shù)沒有簽名,在ECMAScript 中無法實(shí)現(xiàn)接口繼承。ECMAScript 只支持實(shí)現(xiàn)繼承

原型鏈繼承

原型鏈?zhǔn)荍avascript實(shí)現(xiàn)繼承的主要方法

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
}
function SubType(){
    this.subproperty = false;
}
//繼承SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
    return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue())//true

//instanceof用于測試實(shí)例與原型鏈中出現(xiàn)過的構(gòu)造函數(shù)的關(guān)系
console.log(instance instanceof object) //true
console.log(instance instanceof SuperType) //true
console.log(instance instanceof SubType) //true

console.log(Object.prototype.isPrototypeof(instance)) //true
console.log(SuperType.prototype.isPrototypeof(instance)) //true
console.log(SubType.prototype.isPrototypeof(instance)) //true

實(shí)踐中較少多帶帶使用原型鏈繼承

注意:

instance.constructure現(xiàn)在指向的是SuperType

instance.toString現(xiàn)在指向的是Object.prototype

SuperType中的引用值類型會(huì)在所有SubType中共享。

創(chuàng)建SubType實(shí)例時(shí),無法向SuperType的構(gòu)造函數(shù)傳遞參數(shù)(在不影響所有對象實(shí)例的情況下)

易錯(cuò)點(diǎn)

SubType、SuperType添加原型方法的代碼要放在替換原型的語句之后。否則SubType添加的原型方法會(huì)失效,因?yàn)樵蛯ο蟊惶鎿Q了。

不能通過字面量創(chuàng)建SubType的原型對象。因直接對原型賦值字面量對象會(huì)替換SubType的原型,打破了原型鏈。

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

解決了Javascript原型鏈繼承中引用值類型被共享的問題

function SuperType(){
    this.colors=["red","blue","green"];
}
function SubType(){
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"

var instance2 = new SubType();
alert(instance2.colors);//"red,blue,green"

通過call(this)apply(this)我們再SubType的實(shí)例環(huán)境下調(diào)用了SuperType的構(gòu)造函數(shù),因此在SubType對象上執(zhí)行了SuperType的對象初始化代碼,因此每個(gè)SubType都具有了自己的colors屬性

優(yōu)勢

可以傳遞在子類構(gòu)造函數(shù)中向超類構(gòu)造函數(shù)傳遞參數(shù)

問題

因?yàn)榉椒ǘ荚跇?gòu)造函數(shù)中定義的,因此無法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)對象都重新定義了一次方法。

無論什么情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。

注意

為了確保SuperType構(gòu)造函數(shù)不會(huì)重寫子類屬性,應(yīng)在調(diào)用SuperType的構(gòu)造函數(shù)之后再添加子類自身的屬性。

組合繼承

將原型鏈和借用構(gòu)造函數(shù)組合到一塊,發(fā)揮二者之長的一種繼承模式。

原型鏈實(shí)現(xiàn)對屬性和方法的復(fù)用。

借用構(gòu)造函數(shù)實(shí)現(xiàn)對實(shí)例屬性的繼承。

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    console.log(this.name);
};
function SubType(name, age){
    //繼承屬性
    SuperType.call(this, name);
    this.age = age;
}
//繼承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    console.log(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";

instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
console.log(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
原型式繼承

原型式繼承并沒有使用嚴(yán)格意義上的構(gòu)造函數(shù)。是借助原型可以基于已有的對象創(chuàng)建新對象,同時(shí)還不必因此創(chuàng)建自定義類型。

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

在object()函數(shù)內(nèi)部,先創(chuàng)建了一個(gè)臨時(shí)性的構(gòu)造函數(shù),然后將傳入的對象作為這個(gè)構(gòu)造函數(shù)的原型,最后返回了這個(gè)臨時(shí)類型的一個(gè)新實(shí)例。從本質(zhì)上講,object()對傳入其中的對象執(zhí)行了一次淺復(fù)制。
ECMAScript 5 通過新增Object.create()方法規(guī)范化了原型式繼承。這個(gè)方法接收兩個(gè)參數(shù):

一個(gè)用作新對象原型的對象和(可選的)

一個(gè)為新對象定義額外屬性的對象。

在傳入一個(gè)參數(shù)的情況下,Object.create()object()方法的行為相同。
Object.create()方法的第二個(gè)參數(shù)與Object.defineProperties()方法的第二個(gè)參數(shù)格式相同:每個(gè)屬性都是通過自己的描述符定義的。以這種方式指定的任何屬性都會(huì)覆蓋原型對象上的同名屬性。
在沒有必要興師動(dòng)眾地創(chuàng)建構(gòu)造函數(shù),而只想讓一個(gè)對象與另一個(gè)對象保持類似的情況下,原型式繼承是完全可以勝任的。

寄生式繼承

創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對象,最后再像真地是它做了所有工作一樣返回對象

function createAnother(original){
    //通過調(diào)用函數(shù)創(chuàng)建一個(gè)新對象,任何能夠返回新對象的函數(shù)都適用該模式
    var clone = object(original); 
        clone.sayHi = function(){ //以某種方式來增強(qiáng)這個(gè)對象
        alert("hi");
    };
    return clone; //返回這個(gè)對象
}
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

問題

無法做到函數(shù)復(fù)用而降低效率

寄生組合式繼承

由于組合繼承兩次調(diào)用了SuperType的構(gòu)造函數(shù),SubType就具有了兩組SuperType的屬性:一組在實(shí)例上,一組在SubType 原型中。
寄生組合式繼承通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。
基本思路:不必為了指定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無非就是超類型原型的一個(gè)副本而已。
本質(zhì):使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。

function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); //創(chuàng)建對象
    prototype.constructor = subType; //增強(qiáng)對象
    subType.prototype = prototype; //指定對象
}

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
};

優(yōu)勢

高效率:只調(diào)用了一次SuperType 構(gòu)造函數(shù),并且因此避免了在SubType.prototype 上面創(chuàng)建不必要的、多余的屬性。

原型鏈還能保持不變;因此,還能夠正常使用instanceof 和isPrototypeOf()

寄生組合式繼承是引用類型最理想的繼承范式。

YUI 的YAHOO.lang.extend()方法采用了寄生組合繼承,從而讓這種模式首次出現(xiàn)在了一個(gè)應(yīng)用非常廣泛的JavaScript 庫中。

node中的util.inherits繼承

寄生組合式繼承與寄生組合式繼承中inheritPrototype功能一致,因此如果不希望在子類間共享引用類型值屬性,還需組合借用構(gòu)造函數(shù)繼承。

exports.inherits = function(ctor,superCtor){
    ctor.super_ = superCtor;
    ctor.prototype = Object.create(superCtor.prototype,{
        constructor:{
            value:ctor,
            enumerable:false,
            writable:true,
            configurable:true
        }
    };
};

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

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

相關(guān)文章

  • javascript繼承你了解多少?

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

    baishancloud 評論0 收藏0
  • Javascript 設(shè)計(jì)模式讀書筆記(三)——繼承

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

    cangck_X 評論0 收藏0
  • 講清楚之 javascript 對象繼承

    摘要:中的繼承并不是明確規(guī)定的,而是通過模仿實(shí)現(xiàn)的。繼承中的繼承又稱模擬類繼承。將函數(shù)抽離到全局對象中,函數(shù)內(nèi)部直接通過作用域鏈查找函數(shù)。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質(zhì)區(qū)別是屬性查找方式的不同。 這一節(jié)梳理對象的繼承。 我們主要使用繼承來實(shí)現(xiàn)代碼的抽象和代碼的復(fù)用,在應(yīng)用層實(shí)現(xiàn)功能的封裝。 javascript 的對象繼承方式真的是百花齊放,屬性繼承、原型繼承、...

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

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

    kid143 評論0 收藏0
  • 徹底搞懂JavaScript繼承

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

    _ivan 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<