最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS Pro-深入面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的詳解

 更新時(shí)間:2013年05月07日 17:00:25   作者:  
一般的面向?qū)ο蟪绦蛘Z(yǔ)言,有兩種繼承方法——接口繼承(interface inheritance)和實(shí)現(xiàn)繼承(implementation inheritance)。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。在JavaScript中,函數(shù)沒(méi)有簽名,所以在JavaScript只支持實(shí)現(xiàn)繼承,而且主要是依靠原型鏈(prototype chaining)來(lái)是實(shí)現(xiàn)的

原型鏈(prototype chaining):

利用原型來(lái)繼承屬性和方法?;仡櫼幌聵?gòu)造函數(shù)(constructor),原型對(duì)象(prototype)和實(shí)例(instance)的關(guān)系。每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype屬性,該屬性指向一個(gè)prototype對(duì)象;prototype對(duì)象也有constructor屬性,指向該函數(shù);而實(shí)例也有一個(gè)內(nèi)部指針(__proto__)指向這個(gè)prototype對(duì)象。如果這個(gè)prototype對(duì)象是另外一個(gè)對(duì)象的實(shí)例會(huì)是怎樣的呢?這樣該prototype對(duì)象就包含一個(gè)指向另一個(gè)類(lèi)型的指針,相應(yīng)地,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。

JS的繼承很簡(jiǎn)單,就是把子類(lèi)的prototype設(shè)為父類(lèi)的一個(gè)(實(shí)例化)對(duì)象

復(fù)制代碼 代碼如下:

function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function SubType(){
    this.subproperty = false;
}

//inherit from SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function (){
    return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue());   //true

最終的結(jié)果:instance的__proto__指向SubType.prototype對(duì)象,而SubType.prototype對(duì)象的__proto__屬性又指向SuperType.prototype對(duì)象。getSuperValue()是一個(gè)方法,所以仍然存在于原型中,而property是一個(gè)實(shí)例屬性,所以現(xiàn)在存在于SubType.prototype這個(gè)實(shí)例中。  instance.constructor現(xiàn)在指向的是SuperType,這是由于SubType.prototype指向SuperType.prototype,而SuperType.prototype的constructor屬性指向SuperType函數(shù),所以instance.constructor指向SuperType。

默認(rèn)情況下,所有引用類(lèi)型都繼承Object。這是因?yàn)樗泻瘮?shù)的原型對(duì)象,默認(rèn)都是Object的一個(gè)實(shí)例,所以內(nèi)部prototype(__proto__)指向Object.Prototype。

原型和實(shí)例的關(guān)系:可以使用2種方法來(lái)確定原型與實(shí)例之間的關(guān)系。
- instancef操作符:使用該操作符來(lái)測(cè)試實(shí)例與原型鏈中出現(xiàn)過(guò)的構(gòu)造函數(shù),都會(huì)返回true

復(fù)制代碼 代碼如下:

alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true

- isPrototypeOf()方法:只要是原型鏈中出現(xiàn)過(guò)的原型,都可以說(shuō)是該原型鏈所派生的實(shí)例的原型。
復(fù)制代碼 代碼如下:

alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true

給子類(lèi)添加方法的注意點(diǎn):我們有的時(shí)候會(huì)給子類(lèi)添加方法,或者是重寫(xiě)父類(lèi)的某些方法。這個(gè)時(shí)候就要注意,這些方法必須在繼承后再定義。以下的例子里,SubType在繼承SuperType后,我們給它添加了新的方法getSubValue(),而且重寫(xiě)了getSuperValue()方法。對(duì)于后者,只有SubType的實(shí)例才會(huì)使用重寫(xiě)的方法,SuperType的實(shí)例還是會(huì)使用原有的getSuperValue()方法。
復(fù)制代碼 代碼如下:

function SuperType(){
  this.property = true;
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
};
function SubType(){
  t his.subproperty = false;
}
//inherit from SuperType
SubType.prototype = new SuperType();
//new method
SubType.prototype.getSubValue = function (){
  return this.subproperty;
};
//override existing method
SubType.prototype.getSuperValue = function (){
  return false;
};
var instance = new SubType();
alert(instance.getSuperValue()); //false

另外一個(gè)需要注意的是,通過(guò)原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,因?yàn)檫@樣會(huì)重寫(xiě)原型鏈。如下面的代碼,在SubType繼承SuperType以后,使用對(duì)象字面量給原型添加方法,但這樣做,會(huì)重寫(xiě)SubType原型,重寫(xiě)后的SubType.prototype包含的是一個(gè)Object的實(shí)例,從而也切斷了與SuperType的關(guān)系。
復(fù)制代碼 代碼如下:

function SuperType(){
  this.property = true;
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
};
function SubType(){
  this.subproperty = false;
}
//inherit from SuperType
SubType.prototype = new SuperType();
//try to add new methods - this nullifies the previous line
SubType.prototype = {
  getSubValue : function (){
    return this.subproperty;
  },
  someOtherMethod : function (){
    return false;
  }
};
var instance = new SubType();
alert(instance.getSuperValue()); //error!

原型鏈的問(wèn)題:和原型一樣,當(dāng)使用引用類(lèi)型值的時(shí)候,原型鏈就會(huì)出問(wèn)題了?;仡櫼幌轮暗膬?nèi)容,包含一個(gè)引用類(lèi)型值的原型屬性會(huì)被所有實(shí)例共享,這就是為什么我們要把引用類(lèi)型值在構(gòu)造函數(shù)中定義,而不是在原型中定義。在通過(guò)原型鏈實(shí)現(xiàn)繼承時(shí),原型實(shí)際上會(huì)變成另一個(gè)類(lèi)型的實(shí)例,于是,原先的實(shí)例屬性也順利成章的變成現(xiàn)在的原型屬性了。
復(fù)制代碼 代碼如下:

function SuperType(){
  this.colors = [“red”, “blue”, “green”];
}
function SubType(){
}
//inherit from SuperType
SubType.prototype = new SuperType();
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,black”

在SuperType構(gòu)造函數(shù)中,我們定義了一個(gè)colors數(shù)組,每一個(gè)SuperType實(shí)例都會(huì)擁有它自己的這個(gè)colors數(shù)組。但是當(dāng)SubType使用原型鏈繼承SuperType以后,SubType.prototype變成SuperType的一個(gè)實(shí)例,因此它擁有自己的colors屬性,也就是說(shuō)SubType.prototype.colors屬性。所以,當(dāng)創(chuàng)建SubType實(shí)例的時(shí)候,所有實(shí)例都共享這一屬性了。如上面的代碼所示。

第二個(gè)問(wèn)題就是:在創(chuàng)建子類(lèi)的實(shí)例時(shí),不能向超類(lèi)的構(gòu)造函數(shù)中傳遞參數(shù)。實(shí)際上,應(yīng)該說(shuō)是沒(méi)有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類(lèi)的構(gòu)造函數(shù)傳遞參數(shù)。由于這些問(wèn)題,我們不會(huì)單獨(dú)使用原型鏈。

--------------------------------------------------------------------------------

借用構(gòu)造函數(shù)(Contructor stealing):
為了解決上述問(wèn)題,開(kāi)發(fā)人員發(fā)明了一種叫做借用構(gòu)造函數(shù)的技術(shù)。這種技術(shù)的思路就是:在子類(lèi)型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類(lèi)型構(gòu)造函數(shù)。(函數(shù),只不過(guò)是在特定環(huán)境中執(zhí)行代碼的對(duì)象?)我們可以通過(guò)使用apply()或call()方法在新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)。

復(fù)制代碼 代碼如下:

function SuperType(){
  this.colors = [“red”, “blue”, “green”];
}
function SubType(){
  //inherit from SuperType
  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”

我們?cè)赟ubType里使用call()方法調(diào)用SuperType的構(gòu)造函數(shù),實(shí)際上就是在新的SubType對(duì)象上執(zhí)行SuperType()函數(shù)中定義的所有對(duì)象初始化代碼。結(jié)果就是每個(gè)SubType實(shí)例都具有自己的colors屬性的副本。

傳遞參數(shù):使用借用構(gòu)造函數(shù)方法的一個(gè)很大的好處在于就是,我們可以從子類(lèi)的構(gòu)造函數(shù)傳遞參數(shù)到父類(lèi)的構(gòu)造函數(shù)中。

復(fù)制代碼 代碼如下:

function SuperType(name){
  this.name = name;
}
function SubType(){
  //inherit from SuperType passing in an argument
  SuperType.call(this, “Nicholas”);
  //instance property
  this.age = 29;
}
var instance = new SubType();
alert(instance.name); //”Nicholas”;
alert(instance.age); //29

新的SuperType構(gòu)造函數(shù)新增了一個(gè)參數(shù)name,我們?cè)赾all SuperType的同時(shí),往SuperType傳遞參數(shù)"Nicholas"。為了不讓超類(lèi)型的構(gòu)造函數(shù)重寫(xiě)子類(lèi)型的屬性,可以在調(diào)用超類(lèi)型構(gòu)造函數(shù)后再定義子類(lèi)的屬性。

借用構(gòu)造函數(shù)的問(wèn)題:方法都在構(gòu)造函數(shù)中定義,無(wú)法復(fù)用。而且在超類(lèi)型的原型中定義的方法,對(duì)子類(lèi)型而言是不可見(jiàn)的。結(jié)果所有類(lèi)型都只能使用構(gòu)造函數(shù)模式。

--------------------------------------------------------------------------------

組合繼承:
結(jié)合原型鏈及借用構(gòu)造函數(shù)各自的優(yōu)點(diǎn)的一種繼承模式。使用原型鏈繼承原型屬性及方法,使用借用構(gòu)造函數(shù)來(lái)繼承實(shí)例屬性。如下面例子,我們使用call()方法調(diào)用SuperType的構(gòu)造函數(shù)(每個(gè)SubType實(shí)例都擁有自己的name和colors屬性,以及SubType的age屬性);然后再把SuperType實(shí)例賦值給SubType的原型,使其繼承SuperType的sayName()方法(每個(gè)實(shí)例都共用這個(gè)方法)。

復(fù)制代碼 代碼如下:

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    //inherit properties
    SuperType.call(this, name);
    this.age = age;
}
//inherit methods
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
    alert(this.age);
};

var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27


原型式繼承(Prototypal Inheritance):
復(fù)制代碼 代碼如下:

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


寄生式繼承(Parasitic Inheritance):

缺點(diǎn)同構(gòu)造函數(shù)

相關(guān)文章

  • JS動(dòng)態(tài)給對(duì)象添加事件的簡(jiǎn)單方法

    JS動(dòng)態(tài)給對(duì)象添加事件的簡(jiǎn)單方法

    下面小編就為大家?guī)?lái)一篇JS動(dòng)態(tài)給對(duì)象添加事件的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • json對(duì)象轉(zhuǎn)字符串如何實(shí)現(xiàn)

    json對(duì)象轉(zhuǎn)字符串如何實(shí)現(xiàn)

    本文將介紹js json對(duì)象與字符串如何實(shí)現(xiàn)轉(zhuǎn)換,有需要的朋友可以參考下
    2012-12-12
  • 分享JavaScript監(jiān)聽(tīng)全部Ajax請(qǐng)求事件的方法

    分享JavaScript監(jiān)聽(tīng)全部Ajax請(qǐng)求事件的方法

    最近在做一個(gè)小項(xiàng)目,引入了第三方j(luò)s文件,這個(gè)文件會(huì)調(diào)用XMLHttpRequest向服務(wù)器發(fā)送 Ajax請(qǐng)求,但是我有需要監(jiān)聽(tīng)其Ajax請(qǐng)求的某些事件,以便額外地執(zhí)行其他腳本。于是稍微看了看監(jiān)聽(tīng) Ajax請(qǐng)求的事件方法,在這里分享給大家。有需要的朋友們可以參考借鑒。
    2016-08-08
  • JS上傳前預(yù)覽圖片實(shí)例

    JS上傳前預(yù)覽圖片實(shí)例

    上傳圖片對(duì)圖片進(jìn)行一下預(yù)覽,可以了解圖片上傳后大概會(huì)是什么樣子,此功能用js實(shí)現(xiàn),然后在fileupload控件的change事件中調(diào)用,這樣當(dāng)用fileupload選擇完圖片以后,圖片就會(huì)自動(dòng)顯示出來(lái)了。功能很簡(jiǎn)單,卻很實(shí)用。
    2013-03-03
  • JavaScript 中的12種循環(huán)遍歷方法【總結(jié)】

    JavaScript 中的12種循環(huán)遍歷方法【總結(jié)】

    本文給大家總結(jié)了12種JavaScript 中的1循環(huán)遍歷方法,每種方法通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • 讓GoogleCode的SVN下的HTML文件在FireFox下正常顯示.

    讓GoogleCode的SVN下的HTML文件在FireFox下正常顯示.

    GoogleCode可以作為免費(fèi)的穩(wěn)定的靜態(tài)資源空間來(lái)使用,比如JQuery的文檔就在上面
    2009-05-05
  • javascript執(zhí)行上下文、變量對(duì)象實(shí)例分析

    javascript執(zhí)行上下文、變量對(duì)象實(shí)例分析

    這篇文章主要介紹了javascript執(zhí)行上下文、變量對(duì)象,結(jié)合實(shí)例形式分析了javascript執(zhí)行上下文、變量對(duì)象相關(guān)概念、原理、用法與操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04
  • JS請(qǐng)求servlet功能示例

    JS請(qǐng)求servlet功能示例

    這篇文章主要介紹了JS請(qǐng)求servlet功能,結(jié)合具體實(shí)例形式分析了javascript使用ajax請(qǐng)求servlet端響應(yīng)的主要功能代碼與相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • js跨域請(qǐng)求數(shù)據(jù)的3種常用的方法

    js跨域請(qǐng)求數(shù)據(jù)的3種常用的方法

    這篇文章主要介紹了js跨域請(qǐng)求數(shù)據(jù)的3種常用的方法,需要的朋友可以參考下
    2015-12-12
  • javascript高級(jí)的文件目錄排序代碼

    javascript高級(jí)的文件目錄排序代碼

    這幾天在做一個(gè)文件管理的模塊,里面有排序的功能,產(chǎn)品經(jīng)理看了說(shuō)希望能做出更加智能的文件排序功能,就像是win7的名稱排序一樣,主要就是文件名中的數(shù)字會(huì)按大小排序,而不是直接按ascii碼 ,這兩天晚上沒(méi)事,就先寫(xiě)了這個(gè)排序方法,下個(gè)版本中就可以用上了
    2010-08-08

最新評(píng)論

石泉县| 明溪县| 莱州市| 兴仁县| 兴化市| 宁南县| 墨江| 洛川县| 彭山县| 宜兴市| 锦屏县| 杂多县| 绥棱县| 米脂县| 额尔古纳市| 基隆市| 莱芜市| 武功县| 昂仁县| 兰坪| 铜山县| 乌拉特前旗| 监利县| 全州县| 九龙坡区| 托克逊县| 棋牌| 南溪县| 宁德市| 铜陵市| 郎溪县| 城市| 沙雅县| 绥滨县| 调兵山市| 延津县| 大连市| 建阳市| 习水县| 禄丰县| 义马市|