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

資訊專欄INFORMATION COLUMN

Javascript 設(shè)計(jì)模式讀書(shū)筆記(三)——繼承

cangck_X / 448人閱讀

摘要:的繼承方式屬于原型式繼承,非常靈活。當(dāng)使用關(guān)鍵字執(zhí)行類的構(gòu)造函數(shù)時(shí),系統(tǒng)首先創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象會(huì)繼承自構(gòu)造函數(shù)的原型對(duì)象新對(duì)象的原型就是構(gòu)造函數(shù)的屬性。也就是說(shuō),構(gòu)造函數(shù)用來(lái)對(duì)生成的新對(duì)象進(jìn)行一些處理,使這個(gè)新對(duì)象具有某些特定的屬性。

繼承這個(gè)東西在Javascript中尤其復(fù)雜,我掌握得也不好,找工作面試的時(shí)候在這個(gè)問(wèn)題上栽過(guò)跟頭。Javascript的繼承方式屬于原型式繼承,非常靈活。因此Javascript的繼承方式除了基于類的繼承之外還有基于原型的原型式繼承。

繼承是什么

看了這個(gè)詞的第一反應(yīng)我聯(lián)想到了財(cái)產(chǎn)繼承,在一般情況下,父母的遺產(chǎn)由子女繼承,也就是說(shuō)子女將會(huì)獲得財(cái)產(chǎn)的使用權(quán)。而Javascript中的繼承與現(xiàn)實(shí)生活中的財(cái)產(chǎn)繼承還是有區(qū)別的。首先,Javascript中的父類和子類可以同時(shí)并存,而遺產(chǎn)么,什么樣的財(cái)產(chǎn)叫遺產(chǎn)呢?其次,財(cái)產(chǎn)是花了就沒(méi)了,而JS里的繼承則是子類能夠繼承父類的方法,可以重復(fù)使用,減少代碼量。當(dāng)幾個(gè)類都需要一個(gè)相似的方法時(shí),使用繼承可以從同一個(gè)類中繼承相同的方法,而不用對(duì)每個(gè)類重復(fù)地復(fù)制粘貼了。

不用在定義上糾纏過(guò)久,下面討論一下實(shí)現(xiàn)繼承的一些方法。

繼承的基本方法

開(kāi)頭便說(shuō)到了JS的繼承方式分為基于類的繼承(簡(jiǎn)稱類式繼承)和基于原型鏈的繼承(簡(jiǎn)稱原型式繼承)。

類式繼承

類式繼承的特點(diǎn)就是使用函數(shù)聲明類,通過(guò)new關(guān)鍵字創(chuàng)建實(shí)例。

創(chuàng)建類的方法很簡(jiǎn)單,一般可以寫成這樣:

function Blog(address) {
  this.address = address;
}

Blog.prototype.getAddress = function() {
  return this.address;
}

創(chuàng)建該類的實(shí)例通過(guò)new關(guān)鍵字即可:

var blog = new Blog("classicemi.github.io");
blog.getAddress(); // "classicemi.github.io"

當(dāng)使用new關(guān)鍵字時(shí),它和通過(guò)一般方式執(zhí)行函數(shù)的區(qū)別在于函數(shù)的執(zhí)行方式會(huì)改變。當(dāng)使用new關(guān)鍵字執(zhí)行Blog類的構(gòu)造函數(shù)時(shí),系統(tǒng)首先創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象會(huì)繼承自構(gòu)造函數(shù)Blog的原型對(duì)象(新對(duì)象的原型就是構(gòu)造函數(shù)的prototype屬性)。再將this關(guān)鍵字綁定到新對(duì)象上,再返回該新對(duì)象。也就是說(shuō),構(gòu)造函數(shù)用來(lái)對(duì)生成的新對(duì)象進(jìn)行一些處理,使這個(gè)新對(duì)象具有某些特定的屬性。

創(chuàng)建一個(gè)繼承Blog的類就需要手工完成和new運(yùn)算符相似的工作了。

function MyBlog(address, author) {
  Blog.call(this, address);
  this.author = author;
}

當(dāng)通過(guò)new關(guān)鍵字調(diào)用MyBlog構(gòu)造函數(shù)時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)新對(duì)象(這步是自動(dòng)的,this即為這個(gè)新對(duì)象),然后在this上調(diào)用超類Blog的構(gòu)造函數(shù),再給this添加一些MyBlog類特有的不是繼承自Blog類的屬性,最后將新對(duì)象this返回(這步也是自動(dòng)的)。

下面為了繼承Blog類的方法,需要設(shè)置原型鏈,使MyBlog類能夠在原型鏈上找到繼承自Blog類的方法。

MyBlog.prototype = new Blog(); // MyBlog類的原型是Blog類的一個(gè)實(shí)例
MyBlog.prototype.constructor = MyBlog; // 上一步執(zhí)行后prototype的constructor屬性會(huì)變成Blog,需要修改回來(lái)
MyBlog.prototype.getAuthor = function() { // 給MyBlog添加自己的方法
  return this.author;
}

通過(guò)這些操作后,MyBlog類就聲明好了,它繼承了Blog類的屬性和方法,創(chuàng)建MyBlog類實(shí)例的方法和創(chuàng)建Blog類實(shí)例的方法一樣,直接使用new關(guān)鍵字調(diào)用構(gòu)造函數(shù)即可。

原型式繼承

之前的類式繼承是為了模仿其他一些面向?qū)ο笳Z(yǔ)言的特點(diǎn)而創(chuàng)造的,并沒(méi)有真正體現(xiàn)Javascript語(yǔ)言本身的特點(diǎn),下面要說(shuō)的原型式繼承則是利用JS的原型特性而實(shí)現(xiàn)的繼承方式。

使用原型式繼承時(shí),不需要像類式繼承一樣用一個(gè)類(構(gòu)造函數(shù))來(lái)定義對(duì)象的結(jié)構(gòu),而可以用對(duì)象字面量的方式直接創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象是作為原型存在的,被稱作原型對(duì)象(prototype object)。就像工廠生產(chǎn)車間里的模具一樣,為以后生產(chǎn)出的零件提供了參考原型。

還是以之前的BlogMyBlog類為例:

// Blog原型對(duì)象
var Blog = {
  address: "classicemi.github.io", // 屬性只是作為默認(rèn)值,一般都會(huì)被改寫
  getAddress: function() {
    return this.address;
  }
};

這里沒(méi)有像用一個(gè)構(gòu)造函數(shù)來(lái)定義Blog類的結(jié)構(gòu),將方法添加在Blog.prototype上。這里定義的Blog對(duì)象只是作為原型存在,為繼承Blog類的對(duì)象提供一些方法。

現(xiàn)在原型對(duì)象有了,要?jiǎng)?chuàng)建繼承該原型對(duì)象對(duì)應(yīng)的類的新類應(yīng)該怎么做呢?利用JS的原型鏈特性,只要將新類的原型設(shè)為該原型對(duì)象即可。按照這種思路可以寫出子類MyBlog的創(chuàng)建方法:

function MyBlogConstrucFunc() {}
MyBlogConstrucFunc.prototype = Blog;
var MyBlog = new MyBlogConstrucFunc();

通過(guò)new運(yùn)算符調(diào)用MyBlogConstrucFunc函數(shù),返回的是一個(gè)空對(duì)象,這個(gè)空對(duì)象的prototype屬性指向原型對(duì)象Blog。在返回的空對(duì)象中,還可以添加MyBlog類自有的屬性和方法。

不過(guò)通過(guò)這三行代碼實(shí)現(xiàn)子類對(duì)超類的繼承還是有些冗余,我們可以實(shí)現(xiàn)一個(gè)方法來(lái)實(shí)現(xiàn)對(duì)超類的繼承,將超類作為該方法的參數(shù)傳入并在最后將空對(duì)象返回即可。

function clone(object) {
  function F() {}
  F.prototype = object;
  return new F();
}
Mixin Class

以上所討論的是比較嚴(yán)格的繼承方式,有的時(shí)候,我們可能只想對(duì)某個(gè)函數(shù)進(jìn)行重用,并不需要完全的繼承,那么我們可以將函數(shù)以擴(kuò)充的方式在類之間進(jìn)行共享。對(duì)于重用頻率比較高的方法,我們可以將它們歸并在一個(gè)類中,然后用這個(gè)類去擴(kuò)充其他的類。這種方法稱為摻元類(mixin class)。這種處理方法在很多JS庫(kù)(比如jQueryUnderscore)中都有用到,是一種擴(kuò)充工具函數(shù)的好方法。

var Mixin = function() {}
Mixin.prototype = {
  serialize: function() {
    var output = [];
    for(key in this) {
      output.push(key + ": " + this[key]);
    }
    return output.join(", ");
  }
  ...
};

為了能方便地將Mixin類中的方法添加到其他類中,我們可以擴(kuò)展工具函數(shù)augment

function augment(receivingClass, givingClass) {
  if (arguments[2]) { // 可接受三個(gè)參數(shù),第三個(gè)參數(shù)為需添加的方法,多個(gè)方法可用數(shù)組將方法名傳入
    if (arguments[2] instanceOf Array) {
      for (var i = 0, len = arguments[2].length; i < len; i++) {
        if (!receivingClass.prototype[arguments[2][i]]) {
          receivingClass.prototype[arguments[2][i]] = givingClass.prototype[arguments[2][i]];
        }
      }
    } else if (typeof arguments[2] === "string") {
      if (!receivingClass.prototype[arguments[2]]) {
        receivingClass.prototype[arguments[2]] = givingClass.prototype[arguments[2]];
      }
    }
  } else {
    for (methodName in givingClass.prototype) {
      if (!receivingClass.prototype[methodName]) {
        receivingClass.prototype[methodName] = givingClass.prototype[methodName];
      }
    }
  }
}

這時(shí)我們?nèi)绻o其他類添加Mixin中的方法的話可以直接這樣寫:

augment(MyBlog, Mixin);
類式繼承和原型式繼承的對(duì)比

類式繼承存在的意義很大一部分是為了滿足對(duì)Javascript的特性還不熟悉的程序員,畢竟這種方法是強(qiáng)行為了模仿其他面向?qū)ο笳Z(yǔ)言的特性而創(chuàng)造的。Javascript的原型式特征在父類和子類之間建立了一種雙向的聯(lián)系,這是JS區(qū)別于其他語(yǔ)言的特點(diǎn)。
原型式繼承發(fā)揮了JS的特性,所有的子類繼承的方法會(huì)通過(guò)原型鏈逐級(jí)向父類查找,因此用于繼承的方法在內(nèi)存中只會(huì)保存一份,這樣可以節(jié)約內(nèi)存。只有在對(duì)子類的某個(gè)方法進(jìn)行直接設(shè)置,將繼承而來(lái)的方法覆蓋的時(shí)候才會(huì)對(duì)新方法多帶帶生成副本。

封裝對(duì)繼承的影響

一個(gè)經(jīng)過(guò)封裝的類,它的公用方法和特權(quán)方法可以被繼承下來(lái),因?yàn)樗鼈兪翘砑釉谠玩溕系模谧鳛闃?gòu)造函數(shù)的時(shí)候可以繼承給子類。而私用方法相當(dāng)于作為了閉包中的變量,與原型鏈無(wú)關(guān),因此不會(huì)被繼承。

父類中的特權(quán)方法可以訪問(wèn)父類中的私用屬性,而特權(quán)方法會(huì)被子類繼承,因此子類也可以通過(guò)繼承的特權(quán)方法間接訪問(wèn)父類的私用屬性。但子類中新添加的特權(quán)方法不能訪問(wèn)父類中的私用屬性,因?yàn)槿鄙倭说竭_(dá)父類內(nèi)部的原型鏈“通道”。

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

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

相關(guān)文章

  • JavaScript 語(yǔ)言精粹》讀書(shū)筆記 - 函數(shù)

    摘要:語(yǔ)言精粹讀書(shū)筆記第四章函數(shù)函數(shù)字面量函數(shù)字面量包含個(gè)部分第一部分,保留字第二部分,函數(shù)名,它可以被忽略。這個(gè)超級(jí)延遲綁定使得函數(shù)對(duì)高度復(fù)用。構(gòu)造器調(diào)用模式一個(gè)函數(shù),如果創(chuàng)建的目的就是希望結(jié)合的前綴來(lái)調(diào)用,那它就被稱為構(gòu)造器構(gòu)造。 《JavaScript 語(yǔ)言精粹》 讀書(shū)筆記 第四章 函數(shù) Functions 函數(shù)字面量 函數(shù)字面量包含4個(gè)部分: 第一部分, 保留字 function...

    wdzgege 評(píng)論0 收藏0
  • javascript高級(jí)程序設(shè)計(jì)》第六章 讀書(shū)筆記javascript繼承的6種方法

    摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...

    孫吉亮 評(píng)論0 收藏0
  • 讀書(shū)筆記-1【javascript語(yǔ)言精粹】繼承

    摘要:使用構(gòu)造器有個(gè)嚴(yán)重的危害,如果在調(diào)用構(gòu)造器函數(shù)的時(shí)候忘記使用前綴,不僅不會(huì)綁定到新對(duì)象,還會(huì)污染全局變量原型模式原型模式中,我們采用對(duì)象來(lái)繼承。 構(gòu)造器調(diào)用模式 當(dāng)一個(gè)函數(shù)對(duì)象被創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器會(huì)運(yùn)行類似這樣的代碼: this.prototype = {constructor: this} new一個(gè)函數(shù)事會(huì)發(fā)生: Function.method(new, functio...

    malakashi 評(píng)論0 收藏0
  • 《編寫可維護(hù)的 JavaScript讀書(shū)筆記

    摘要:最近閱讀了編寫可維護(hù)的,在這里記錄一下讀書(shū)筆記。禁止使用,,,的字符串形式。避免使用級(jí)事件處理函數(shù)。讓事件處理程序成為接觸到對(duì)象的唯一函數(shù)。檢測(cè)函數(shù)是檢測(cè)檢測(cè)函數(shù)的最佳選擇。為特定瀏覽器的特性進(jìn)行測(cè)試,并僅當(dāng)特性存在時(shí)即可應(yīng)用特性檢測(cè)。 最近閱讀了《編寫可維護(hù)的 JavaScript》,在這里記錄一下讀書(shū)筆記。書(shū)中主要基于三個(gè)方向來(lái)講解怎么增加代碼的可維護(hù)性:編程風(fēng)格、編程實(shí)踐、自動(dòng)化...

    tuniutech 評(píng)論0 收藏0
  • JavaScript模式讀書(shū)筆記(二)字面量和構(gòu)造函數(shù)

    摘要:對(duì)象字面量定義一個(gè)空對(duì)象這里的空指的是其自身屬性為空,對(duì)象繼承了的屬性和方法添加屬性方法完全刪除屬性方法自定義構(gòu)造函數(shù)用操作符調(diào)用構(gòu)造函數(shù)時(shí),函數(shù)內(nèi)部會(huì)發(fā)發(fā)生以下情況創(chuàng)建一個(gè)新對(duì)象,并且引用了該對(duì)象并繼承了該函數(shù)的原型屬性和方法被加入到的引 對(duì)象字面量 //定義一個(gè)空對(duì)象,這里的空指的是其自身屬性為空,dog對(duì)象繼承了Object.prototype的屬性和方法 var dog={} ...

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

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

0條評(píng)論

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