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

資訊專欄INFORMATION COLUMN

javascript的繼承你了解多少?

baishancloud / 1696人閱讀

摘要:和構(gòu)造函數(shù)前面提到,是個內(nèi)置隱藏屬性,雖然在可以通過訪問,但是其設(shè)計本意是不可被讀取和修改的,那么我們?nèi)绾卫迷玩渷斫⒗^承關(guān)系提供了關(guān)鍵字。到這兒,思路就清晰了,怎么讓對象和對象的相連實現(xiàn)繼承只需把的構(gòu)造函數(shù)的連接到就行了。

什么是繼承?
大多數(shù)人使用繼承不外乎是為了獲得這兩點好處,代碼的抽象和代碼的復(fù)用。
代碼的抽象就不用說了,交通工具和汽車這類的例子數(shù)不勝數(shù),在傳統(tǒng)的OO語言中(比如Java),代碼的抽象更多的是使用接口(interface)來實現(xiàn),而使用繼承更多地是為了代碼的復(fù)用(雖然現(xiàn)在強調(diào)使用組合而不是使用繼承)。

怎么復(fù)用的?打個比方,class A 繼承了 class B,class A便擁有了class B 的public 和 protected類型的變量和方法,用最簡單的方法去想,便是 class B 將 這些屬性和方法直接copy給class A,這樣便實現(xiàn)了繼承。

因此我們可以這樣說,繼承實際上是一種類與類之間的copy行為。

JavaScript中的繼承
在JavaScript中沒有類的概念,只有對象。雖然現(xiàn)在人們經(jīng)常使用class關(guān)鍵字,這讓JavaScript看起來似乎是擁有了”類”,可表面看到的不一定是本質(zhì),class只是一塊糖,嚼碎了才知道里面其實還是原型鏈那一套。因此,JavaScript中的繼承只是對象與對象之間的繼承。反觀繼承的本質(zhì),繼承便是讓子類擁有父類的一些屬性和方法,那么在JavaScript中便是讓一個對象擁有另一個對象的屬性和方法。

所以,這給我了我們一條十分清晰的思路,JavaScript中如何實現(xiàn)繼承?只需讓一個對象擁有另一個對象的屬性和方法,這就實現(xiàn)了。

利用Mixin

既然讓一個對象擁有另一個對象的屬性和方法,首先想到的便是利用Mixin的粗暴方式,直接將對象的屬性和方法強制copy到另一個對象。

就像這樣

function mixin(subObj, parentObj) {
    for (var prop in parentObj) {
        if (!(prop in subObj)) {
            subObj[prop] = parentObj[prop]
        }
    } 
}

當然也可以用ES6中的更優(yōu)雅的Object.assign。

這段代碼就實現(xiàn)了最簡單的從一個對象復(fù)制屬性和方法到另一個對象。然而這種方法有一個缺陷,如果父對象的屬性是引用類型,比如一個對象或者數(shù)組,那么修改子對象的時候勢必會對父對象也造成修改,這顯然不可接受。一種想法是采用深度克隆,然而又可能會有循環(huán)引用的問題。

所以,這種繼承方式,比較適合對簡單對象的拓展,不太適合更復(fù)雜的繼承。

利用原型鏈

首先來說一下什么是原型,原型在JavaScript中,其實就是某個對象的一個屬性。只不過這個屬性很特殊,對于外界一般是不可見(在chrome中可以通過__proto__獲取),我們一般把它叫作[[Prototype]]。這里和函數(shù)的prototype屬性很相似但卻是兩個東西,后面會提到。

那么什么是原型鏈呢,顧名思義就像這樣:

obj1.[[Prototype]] ===> obj2.[[Prototype]] ===> obj3.[[Prototype]]…. ===> Object.prototype

某一對象的原型屬性中保存著另一個對象,以此類推,好像鏈子一樣串起來。

鏈的終點是Object.prototype對象,因此Object.prototype沒有原型。當我們構(gòu)建一個對象,這個對象的默認的原型就是Object.prototype

在chrome中驗證一下:

var a = {}
Object.prototype === a.__proto__  // true

那么我們?nèi)绾斡迷玩湆崿F(xiàn)繼承呢?這要歸功于JavaScript中的委托機制。

當我們獲取一個對象的某個屬性時,比如a.b,會默認調(diào)用一個內(nèi)置的[[Get]]方法,這個[[Get]]方法的算法就是:

在當前對象里查找,找不到則委托給當前對象的[[Prototype]],再找不到則委托給[[Prototype]]的[[Prototype]],直到Object.prototype中也沒找到,則返回undefined。

因此,我們想讓對象a擁有對象b的屬性和方法,即對象a繼承對象b,只需要把b賦值給a的[[Prototype]],利用屬性查找的委托機制,實現(xiàn)了a也”擁有”了b的屬性和方法,而且當a中有和b中的同名屬性時,由于”屏蔽作用”,只有a中的屬性會被優(yōu)先獲取到,實現(xiàn)了override,看起來相當完美。

new 和 “構(gòu)造函數(shù)”

前面提到,[[Prototype]]是個內(nèi)置隱藏屬性,雖然在chrome可以通過__proto__訪問,但是其設(shè)計本意是不可被讀取和修改的,那么我們?nèi)绾卫迷玩渷斫⒗^承關(guān)系?

JavaScript提供了new關(guān)鍵字。

通常,在類似Java這樣的OO語言中,new被用來實例化一個類,然而在JavaScript中,new僅僅是一個函數(shù)調(diào)用的方式!

JavaScript中的函數(shù)也很奇怪,每一個函數(shù)都有一個默認的prototype屬性,這個不同于對象的[[Prototype]]屬性,函數(shù)的prototype是故意暴露出來的,而且這個屬性還不為空,還有prototype還有另一個屬性叫constructor,這個constructor竟然又引用回來了這個函數(shù)本身!于是我們看到的效果是這樣的:

用new來調(diào)用函數(shù)有什么不同的呢?new其實做了三件事:

創(chuàng)建一個新對象

將這個新對象的[[Prototype]]連接到調(diào)用函數(shù)的prototype上

綁定調(diào)用函數(shù)的this并調(diào)用

用代碼來表示就是:

function New(fn) {
    var tmp = {}
    tmp.__proto__ = fn.prototype
    fn.call(tmp)
    return tmp
}

可以看到,new幫我們把對象的[[Prototype]]連接到了函數(shù)的prototype上。

到這兒,思路就清晰了,怎么讓對象a和對象b的[[Prototype]]相連實現(xiàn)a繼承b?

只需把a的”構(gòu)造函數(shù)”的[[Prototype]]連接到b就行了。

來實現(xiàn)一下:

function A() {
    
}
var b = {
    show: function() {
        console.log("這是來自b的方法")
    }
}
A.prototype = b
// 這里修復(fù)了原先的 constructor
A.prototype.constructor = A
var a = new A()
a.show()  // 這是來自b的方法
更簡單的Object.create

ES5中提供的Object.create更簡單粗暴,可以直接創(chuàng)建一個對象并將這個對象的[[Prototype]]指向傳入的對象

var b = {c: 1}
var a = Object.create(b)
console.log(a.c) // 1
模擬類繼承

在JavaScript中沒有類的概念,雖然從ES6開始擁有了class關(guān)鍵字,但其背后仍然是原型鏈作支撐,所以這里還是用最本質(zhì)的原型來模擬”類”的繼承。這才是JavaScript的本來面目!

/**
 * 實現(xiàn) A 繼承 B
 */
function B(b) {
    this.b = b
}
function A(a, b) {
    // 調(diào)用B并綁定this
    B.call(this, b)
    this.a = a
}
A.prototype = Object.assign({}, B.prototype)
A.prototype.constructor = A
var c = new A(1, 2)
console.log(c.a) // 1
// c 擁有了只有B的實例才擁有的 b 屬性
console.log(c.b) // 2
總結(jié)

簡單來說,繼承即是copy和復(fù)用,JavaScript的繼承其實就是利用原型鏈的查找和委托來實現(xiàn)屬性和方法的復(fù)用,new關(guān)鍵字和”構(gòu)造函數(shù)”只是連接原型鏈的工具,這樣的工具還有Object.create。

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

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

相關(guān)文章

  • 前端實習面試匯總

    摘要:題目來源前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來進行一個總結(jié),同樣也希望對正在準備面實習生的童鞋們有所幫助最后一個參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準備找實習,在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實習生面試題自己整理一下。 題目來源:前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    張利勇 評論0 收藏0
  • 前端實習面試匯總

    摘要:題目來源前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來進行一個總結(jié),同樣也希望對正在準備面實習生的童鞋們有所幫助最后一個參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準備找實習,在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實習生面試題自己整理一下。 題目來源:前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    wangzy2019 評論0 收藏0
  • 前端實習面試匯總

    摘要:題目來源前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來進行一個總結(jié),同樣也希望對正在準備面實習生的童鞋們有所幫助最后一個參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準備找實習,在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實習生面試題自己整理一下。 題目來源:前端實習生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    NicolasHe 評論0 收藏0
  • "雙非"應(yīng)屆生校招如何獲得大廠青睞?(內(nèi)附前端大廠面經(jīng)+技術(shù)崗超全求職攻略)

    摘要:拿到秋招的同學,如確定入職需與用人單位簽署三方協(xié)議,以保證雙方的利益不受損失。當然每個崗位所要求的側(cè)重點不同,但卻百變不離其宗。方法論要想達成某個目標都有其特定的方法論,學習技術(shù)也不例外,掌握適當?shù)膶W習方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準備春招,其中遇到不少坑,也意識到自己走過的彎路。故寫了這篇文章總結(jié)一番,本文適合主動學習的,對自己要學的課程不明確的,對面試有...

    jeffrey_up 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<