亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript繼承基礎講解(原型鏈、借用構造函數、混合模式、原型式繼承、寄生式繼承、寄生組合式繼承)

2019-11-20 14:15:53
字體:
來源:轉載
供稿:網友

說好的講解JavaScript繼承,可是遲遲到現在講解。廢話不多說,直接進入正題。

  既然你想了解繼承,證明你對JavaScript面向對象已經有一定的了解,如還有什么不理解的可以參考《面向對象JS基礎講解,工廠模式、構造函數模式、原型模式、混合模式、動態原型模式》,接下來講一般通過那些方法完成JavaScript的繼承。

  原型鏈

  JavaScript中實現繼承最簡單的方式就是使用原型鏈,將子類型的原型指向父類型的實例即可,即“子類型.prototype = new 父類型();”,實現方法如下:

// 為父類型創建構造函數function SuperType() {  this.name = ['wuyuchang', 'Jack', 'Tim'];  this.property = true;}// 為父類型添加方法SuperType.prototype.getSuerperValue = function() {  return this.property;}// 為子類型創建構造函數function SubType() {  this.test = ['h1', 'h2', 'h3', 'h4'];  this.subproperty = false;}// 實現繼承的關鍵步驟,子類型的原型指向父類型的實例SubType.prototype = new SuperType();// 在此處給子類型添加方法,一定要在實現繼承之后,否則會在將指針指向父類型的實例,則方法為空SubType.prototype.getSubValue = function() {  return this.subproperty;}/* 以下為測試代碼示例 */var instance1 = new SubType();instance1.name.push('wyc');instance1.test.push('h5');alert(instance1.getSuerperValue());    // truealert(instance1.getSubValue());      // falsealert(instance1.name);          // wuyuchang,Jack,Tim,wycalert(instance1.test);          // h1,h2,h3,h4,h5var instance2 = new SubType();alert(instance2.name);          // wuyuchang,Jack,Tim,wycalert(instance2.test);          // h1,h2,h3,h4

可以看到如上的代碼就是通過原型鏈實現的一個簡單的繼承,但看到測試代碼示例中還是存在些問題。相信看了我的博文《面向對象JS基礎講解,工廠模式、構造函數模式、原型模式、混合模式、動態原型模式》的童鞋一定知道原型鏈代碼存在的第一個問題是由于子類型的原型是父類型的實例,也就是子類型的原型中包含的父類型的屬性,從而導致引用類型值的原型屬性會被所有實例所共享。以上代碼的instance1.name.push('wyc');就可以證明此問題的存在。而原型鏈的第二個問題就是:在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。因此我們在實際開發中,很少單獨使用原型鏈。 

   借用構造函數

  為了解決原型鏈中存在的兩個問題,開發人員開始使用一種叫做借用構造函數的技術來解決原型鏈中存在的問題。這種技術的實現思路也挺簡單,只需要在子類型的構造函數內調用父類型的構造函數即可。別忘了,函數只不過是在特定環境中執行代碼的對象,因此可以通過apply()或call()方法執行構造函數。代碼如下:

// 為父類型創建構造函數function SuperType(name) {  this.name = name;  this.color = ['pink', 'yellow'];  this.property = true;  this.testFun = function() {    alert('http://tools.VeVB.COm/');  }}// 為父類型添加方法SuperType.prototype.getSuerperValue = function() {  return this.property;}// 為子類型創建構造函數function SubType(name) {  SuperType.call(this, name);  this.test = ['h1', 'h2', 'h3', 'h4'];  this.subproperty = false;}// 在此處給子類型添加方法,一定要在實現繼承之后,否則會在將指針指向父類型的實例,則方法為空SubType.prototype.getSubValue = function() {  return this.subproperty;}/* 以下為測試代碼示例 */var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);instance1.name.push('hello');instance1.test.push('h5');instance1.color.push('blue');instance1.testFun();            // http://tools.VeVB.COm/alert(instance1.name);            // wuyuchang,Jack,Nick,hello// alert(instance1.getSuerperValue());    // error 報錯alert(instance1.test);            // h1,h2,h3,h4,h5    alert(instance1.getSubValue());        // false    alert(instance1.color);            // pink,yellow,bluevar instance2 = new SubType('wyc');instance2.testFun();            // http://tools.VeVB.COm/alert(instance2.name);            // wyc    // alert(instance2.getSuerperValue());    // error 報錯alert(instance2.test);            // h1,h2,h3,h4alert(instance2.getSubValue());        // falsealert(instance2.color);            // pink,yellow

可以看到以上代碼中子類型SubType的構造函數內通過調用父類型"SuperType.call(this, name);",從而實現了屬性的繼承,也可以在子類型創建實例的時候為父類型傳遞參數了,但新的問題又來了。可以看到我在父類型的構造函數中定義了一個方法:testFun,在父類型的原型中定義了一個方法:getSuperValue??墒窃?span style="color: #ff0000">實例化子類型后仍然是無法調用父類型的原型中定義的方法getSuperValue,只能調用父類型中構造函數的方法:testFun。這就同創建對象中只使用構造函數模式一樣,使得函數沒有復用性可言。考慮到這些問題,借用構造函數的技術也是很少單獨使用的。

組合繼承(原型鏈+借用構造函數)

  顧名思義,組合繼承就是結合使用原型鏈與借用構造函數的優點,組合而成的一個模式。實現也很簡單,既然是結合,那當然結合了兩方的優點,即原型鏈繼承方法,而在構造函數繼承屬性。具體代碼實現如下:

// 為父類型創建構造函數function SuperType(name) {  this.name = name;  this.color = ['pink', 'yellow'];  this.property = true;  this.testFun = function() {    alert('http://tools.VeVB.COm/');  }}// 為父類型添加方法SuperType.prototype.getSuerperValue = function() {  return this.property;}// 為子類型創建構造函數function SubType(name) {  SuperType.call(this, name);  this.test = ['h1', 'h2', 'h3', 'h4'];  this.subproperty = false;}SubType.prototype = new SuperType();// 在此處給子類型添加方法,一定要在實現繼承之后,否則會在將指針指向父類型的實例,則方法為空SubType.prototype.getSubValue = function() {  return this.subproperty;}/* 以下為測試代碼示例 */var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);instance1.name.push('hello');instance1.test.push('h5');instance1.color.push('blue');instance1.testFun();            // http://tools.VeVB.COm/alert(instance1.name);            // wuyuchang,Jack,Nick,helloalert(instance1.getSuerperValue());      // truealert(instance1.test);            // h1,h2,h3,h4,h5    alert(instance1.getSubValue());        // false    alert(instance1.color);            // pink,yellow,bluevar instance2 = new SubType('wyc');instance2.testFun();            // http://tools.VeVB.COm/alert(instance2.name);            // wyc    alert(instance2.getSuerperValue());      // truealert(instance2.test);            // h1,h2,h3,h4alert(instance2.getSubValue());        // falsealert(instance2.color);            // pink,yellow

以上代碼通過SuperType.call(this, name);繼承父類型的屬性,通過SubType.prototype = new SuperType();繼承父類型的方法。以上代碼很方便的解決了原型鏈與借用構造函數所遇到的問題,成為了JavaScript中最為常用的實例繼承的方法。但混合模式也并非沒有缺點,可以看到在以上代碼中在繼承方法的時候實際已經繼承了父類型的屬性,只不過此時對于引用類型屬于共享的,因此在子類型的構造函數內在次調用父類型的構造函數從而繼承了父類型的屬性而去覆蓋了原型中所繼承的屬性,這樣調用兩次構造函數顯然沒有必要,但有什么方法可以解決呢?在解決此問題時先看以下兩個模式。

原型式繼承

  原型式繼承的的實現方法與普通繼承的實現方法不同,原型式繼承并沒有使用嚴格意義上的構造函數,而是借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型。具體代碼如下:

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

代碼示例:

/* 原型式繼承 */function object(o) {  function F() {}  F.prototype = o;  return new F();}var person = {  name : 'wuyuchang',  friends : ['wyc', 'Nicholas', 'Tim']}var anotherPerson = object(person);anotherPerson.name = 'Greg';anotherPerson.friends.push('Bob');var anotherPerson2 = object(person);anotherPerson2.name = 'Jack';anotherPerson2.friends.push('Rose');alert(person.friends);  // wyc,Nicholas,Tim,Bob,Rose

寄生式繼承

/* 寄生式繼承 */function createAnother(original) {  var clone = object(original);  clone.sayHi = function() {    alert('hi');  }  return clone;}

使用示例:

/* 原型式繼承 */function object(o) {  function F() {}  F.prototype = o;  return new F();}   /* 寄生式繼承 */function createAnother(original) {  var clone = object(original);  clone.sayHi = function() {    alert('hi');  }  return clone;}var person = {  name : 'wuyuchang',  friends : ['wyc', 'Nicholas', 'Rose']}var anotherPerson = createAnother(person);anotherPerson.sayHi();

寄生組合式繼承

  前面說過了JavaScrip中組合模式實現繼承的缺點,現在我們就來解決它的缺點,實現思路是,對于構造函數繼承屬性,而原型鏈的混成形式繼承方法,即不用在繼承方法的時候實例化父類型的構造函數。代碼如下:

function object(o) {  function F() {}  F.prototype = o;  return new F();}/* 寄生組合式繼承 */function inheritPrototype(subType, superType) {  var prototype = object(superType.prototype);  prototype.constructor = subType;  subType.prototype = prototype;}

而在使用時只需要將組合模式中的“SubType.prototype = new SuperType();”這行代碼替換成inheritPrototype(subType, superType);即可。寄生組合式繼承的高效率體現在它只調用了一次父類型構造函數,避免了創建不必要的或多余的屬性。與此同時,原型鏈還能保持不變,因此,還能夠正常使用instanceof和isPrototypeof()。這也是目前來說最理想的繼承方式了,目前也在向這種模式轉型。(YUI也使用了這種模式。)

此博文參考《JavaScript高級程序設計第3版》,代碼為經過改寫,更具體,并加了注釋使大家更易懂。如對JS繼承方面有獨到見解的童鞋不別吝嗇,回復您的見解供大家參考!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一区二区成人av| 色噜噜久久综合伊人一本| 日韩精品视频免费专区在线播放| 国产成人精品亚洲精品| 亚洲国产一区二区三区在线观看| 国产日韩专区在线| 国产精品自产拍在线观看| 久久久久久91香蕉国产| 色中色综合影院手机版在线观看| 日韩av影视在线| 久久视频国产精品免费视频在线| 中文字幕日韩专区| 欧美香蕉大胸在线视频观看| 久热在线中文字幕色999舞| 欧美激情在线狂野欧美精品| 亚洲精品国偷自产在线99热| 国产精品大片wwwwww| 欧美在线观看一区二区三区| 国产成人精品av| 欧美视频专区一二在线观看| 国产欧美精品一区二区| 国产精品pans私拍| 国产亚洲aⅴaaaaaa毛片| 国产精品黄页免费高清在线观看| 亚洲人成在线观看网站高清| 日本最新高清不卡中文字幕| 国产精品久久久久久久天堂| 日韩欧美国产视频| 国产97色在线|日韩| 国产精品一区二区久久精品| 亚洲风情亚aⅴ在线发布| 久久久久中文字幕2018| 国产91成人在在线播放| 国内精品400部情侣激情| 日本一区二区在线播放| 97人人做人人爱| 日日狠狠久久偷偷四色综合免费| 中文字幕亚洲综合久久筱田步美| 亚洲韩国青草视频| 亚洲美女性视频| 日韩视频免费看| 91wwwcom在线观看| 精品无人国产偷自产在线| 美女精品视频一区| 日韩精品在线视频美女| 日韩精品在线观看一区二区| 亚洲伊人一本大道中文字幕| 国产精品免费一区二区三区都可以| 国产噜噜噜噜噜久久久久久久久| 亚洲天堂男人天堂女人天堂| 日韩在线欧美在线国产在线| 欧美成人剧情片在线观看| 91麻豆国产精品| 精品动漫一区二区三区| 国产亚洲欧美另类中文| 国语自产精品视频在线看抢先版图片| 亚洲视频欧美视频| 久久精品91久久香蕉加勒比| 久久久精品中文字幕| 亚洲香蕉成人av网站在线观看| 欧美性猛交xxxx偷拍洗澡| 欧美影院成年免费版| 91国产中文字幕| 欧美成人免费小视频| 日韩在线播放一区| 91欧美激情另类亚洲| 亚洲人在线视频| 日本91av在线播放| 亚洲国产99精品国自产| 亚洲乱亚洲乱妇无码| 日韩欧美在线视频免费观看| 富二代精品短视频| 亚洲一区二区黄| 国产精品盗摄久久久| 欧美日本啪啪无遮挡网站| 日韩欧美在线观看视频| 日韩有码在线电影| 欧美最猛黑人xxxx黑人猛叫黄| 91精品国产沙发| 国产成人avxxxxx在线看| 夜色77av精品影院| 97久久精品国产| 在线看片第一页欧美| 国产精品狼人色视频一区| 久久久久久这里只有精品| 久久精品国产一区二区三区| 在线视频欧美日韩精品| 欧美成人在线网站| 国产网站欧美日韩免费精品在线观看| 久久久久日韩精品久久久男男| 久久天天躁狠狠躁夜夜爽蜜月| 国产91精品黑色丝袜高跟鞋| 欧美性20hd另类| 欧美国产中文字幕| 欧美亚洲国产成人精品| 久久91超碰青草是什么| 亚洲国产精品一区二区久| 欧美专区在线视频| 中文字幕综合一区| 亚洲精品国产精品国自产观看浪潮| 日韩欧美在线看| 亚洲成成品网站| 亚洲一区中文字幕| 国产精品白丝av嫩草影院| 这里只有精品视频| 国产一区二区三区免费视频| 中国日韩欧美久久久久久久久| 性夜试看影院91社区| 久久999免费视频| 亚洲片国产一区一级在线观看| 久久人人爽国产| 亚洲视频视频在线| 欧美亚洲国产视频| 日韩av在线一区| 欧美性猛交xxxx富婆弯腰| 51视频国产精品一区二区| 国产suv精品一区二区| 秋霞成人午夜鲁丝一区二区三区| 久久久久久综合网天天| 久久久之久亚州精品露出| 亚洲欧美精品一区二区| 81精品国产乱码久久久久久| 欧美激情中文字幕在线| 精品久久久香蕉免费精品视频| 国产精品普通话| 国产精品日韩在线观看| 精品国产999| 亚洲日韩欧美视频| 亚洲性猛交xxxxwww| 国产91av在线| 日韩精品中文在线观看| 69久久夜色精品国产69| 欧美特黄级在线| 91精品久久久久久久久久久久久| 91久久精品一区| 久久久久久尹人网香蕉| 亚洲四色影视在线观看| 在线亚洲国产精品网| 亚洲精品综合久久中文字幕| 欧美亚洲另类制服自拍| 亚洲精品美女在线观看播放| 成人免费福利视频| 亚洲一区二区国产| 久久久久免费视频| 国内精品免费午夜毛片| 欧美一区二区色| 久久精品国产欧美亚洲人人爽| 日日噜噜噜夜夜爽亚洲精品| 亚洲人成伊人成综合网久久久| 亚洲综合日韩在线| 国产99久久久欧美黑人| 国产免费一区二区三区香蕉精| 国产精品久久久久7777婷婷| 亚洲性日韩精品一区二区| 亚洲精品97久久| 亚洲 日韩 国产第一| 欧美亚洲视频一区二区| 久久久久久久久久久人体| 亚洲免费视频观看| 国产精品一区=区| 午夜精品国产精品大乳美女| 中文字幕欧美日韩va免费视频| 97国产精品免费视频| 色综合久久精品亚洲国产|