国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

重溫JS基礎(chǔ)--繼承

sixleaves / 2329人閱讀

摘要:繼承了如上,我們通過方法借調(diào)了超類的構(gòu)造函數(shù),實(shí)際上是在新創(chuàng)建的實(shí)力環(huán)境下調(diào)用了構(gòu)造函數(shù)。組合繼承組合繼承的基本思想將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊,從而發(fā)揮二者之長(zhǎng)的一種繼承模式。繼承方法在上面這個(gè)例子中,構(gòu)造函數(shù)定義了兩個(gè)屬性和。

在ECMAScript中只支持實(shí)現(xiàn)繼承,而且實(shí)現(xiàn)繼承主要是依靠原型鏈來實(shí)現(xiàn)的。

1. 什么是原型鏈

繼承基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。
構(gòu)造函數(shù),原型對(duì)象和實(shí)例對(duì)象的關(guān)系:每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象包含一個(gè)指向構(gòu)造函數(shù)的指針,實(shí)例對(duì)象包含一個(gè)指向原型對(duì)象的內(nèi)部指針。
假如我們讓原型對(duì)象等于另外一個(gè)構(gòu)造函數(shù)的實(shí)例,那么此時(shí)的原型對(duì)象將包含一個(gè)指向另外一個(gè)原型對(duì)象的指針,且該被指向的原型對(duì)象包含一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。假如另一個(gè)原型對(duì)象又是另一個(gè)類型的實(shí)例,那么上述關(guān)系依然成立,如此層層遞進(jìn),就構(gòu)成了實(shí)例與原型的鏈條,這就是原型鏈的基本概念。用代碼描述如下:

function Super() {
    this.property = true
}
Super.prototype.getSuperValue = function() {
    return this.property
}

function Sub() {
    this.subproperty = false


//繼承Super
Sub.prototype = new Super()
Sub.prototype.getSubValue = function() {
    return this.subproperty
}
var instance = new Sub()
console.log(instance.getSuperValue()) //true

如上代碼,很好的描述了利用原型鏈進(jìn)行繼承。Super和Sub兩個(gè)構(gòu)造函數(shù)。每個(gè)類型分別有一個(gè)屬性和一個(gè)方法。Sub繼承了Spuer,而繼承時(shí)通過創(chuàng)建了Super的實(shí)例,并將該實(shí)例賦給Sub.prototype實(shí)現(xiàn)。這實(shí)現(xiàn)的本質(zhì)是重寫了原型對(duì)象。在確立繼承關(guān)系后我們又給Sub.prototype上面加了一個(gè)新方法。注意現(xiàn)在instance.constructor現(xiàn)在指向的值Super,因?yàn)镾ub.prototype中的constructor被重寫了。

2. 別忘記默認(rèn)的原型

我們知道,所有引用類型默認(rèn)都繼承Object, 而這個(gè)繼承也是通過原型鏈實(shí)現(xiàn)的。所有函數(shù)的默認(rèn)原型對(duì)象都是Object的實(shí)例。因此默認(rèn)原型都會(huì)包含一個(gè)指向內(nèi)部的指針,指向Object.prototype。

3. 確定原型和實(shí)例的關(guān)系

可以通過兩種方式來確定原型和實(shí)例之間的關(guān)系。第一種是通過instanceof操作符,只要用這個(gè)操作符來測(cè)試實(shí)例與原型鏈中出現(xiàn)過的構(gòu)造函數(shù),結(jié)果就會(huì)返回true。

instance instanceof Object //true
instance instanceof Super // true
instance instanceof Sub //true

由于原型鏈的關(guān)系,我們可以說instance是Object, Super, Sub中任何一個(gè)類型的實(shí)例。
第二種方式是使用isPrototypeOf()方法。同樣,只要是原型鏈中出現(xiàn)過得原型,都可以說是該原型鏈所派生的實(shí)例的原型。

Object.prototype.isPrototypeOf(instance) //true
Super.prototype.isPrototypeOf(instance) //true
Sub.prototype.isPrototypeOf(instance) //true
4. 謹(jǐn)慎的定義方法

子類型有時(shí)需要重寫超類中的某個(gè)方法,或者需要添加超類中不存在的某個(gè)方法。給原型添加方法的代碼一定要放在替換原型的語(yǔ)句之后.

function Super() {
    this.property = true
}
Super.prototype.getSuperValue = function() {
    return this.property
}
function Sub() {
    this.subproperty = false
}
//繼承Super
Sub.prototype = new Super()
//添加新方法
Sub.prototype.getSubValue = function() {
    return this.subproperty
}
//重寫超類中的方法
Sub.prototype.getSuperValue = function() {
    return false
}

var instance = new Sub()
console.log(instance.getSuperValue()) //false

還有一點(diǎn)需要注意的是,通過原型鏈繼承的時(shí)候,不能使用對(duì)象字面量的形式創(chuàng)建原型方法。這是因?yàn)闀?huì)重寫原型鏈。

function Super() {
    this.property = true
}
Super.prototype.getSuperValue = function() {
    return this.property
}

function Sub() {
    this.subproperty = false
}
//繼承Super
Sub.prototype = new Super()

//使用字面量添加新方法,會(huì)導(dǎo)致上一行代碼無效

Sub.prototype = {
    getSubValue: function() {
        return this.subproperty
    }
}

var instance = new Sub()
alert(instance.getSuperValue()) //error

如上,Sub繼承了Super,緊接著又將原型替換成了一個(gè)對(duì)象字面量而導(dǎo)致問題。由于現(xiàn)在的原型包含的是一個(gè)Object的實(shí)例,而非SuperType的實(shí)例,因此我們?cè)O(shè)想的原型鏈已經(jīng)被切斷。

5. 原型鏈的問題

使用原型鏈繼承的主要問題還是來自于包含引用類型值得原型。通過原型來實(shí)現(xiàn)繼承時(shí),原型實(shí)際上會(huì)變成另一個(gè)類型的實(shí)例。于是,原先的實(shí)例屬性也就成了現(xiàn)在的原型屬性了。因?yàn)樵蛯傩陨鲜菍?shí)例共享的,那么就會(huì)出現(xiàn)問題。

function Super() {
    this.colors = ["red", "blue", "green"]
}
function Sub() {}

//繼承Super
Sub.prototype = new Super()

var p1 = new Sub()
p1.colors.push("black")

var p2 = new Sub()
console.log(p2.colors) //["red", "blue", "green", "black"]

原型鏈的第二個(gè)問題就是,創(chuàng)建子類型實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)。實(shí)際上,應(yīng)該說是沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù)。

6. 借用構(gòu)造函數(shù)

在解決原型對(duì)象中包含引用類型值所帶來問題得過程中,使用一種叫做借用構(gòu)造函數(shù)的技術(shù)。
基本思想:在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。(函數(shù)只不過是在特定環(huán)境下執(zhí)行代碼的對(duì)象)因此,可以通過使用apply()call()方法可以在新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)。

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

function Sub() {
    //繼承了Super
    Super.call(this)
}

var p = new Sub()
p.colors.push("black")
console.log(p.colors) //"red, blud, green, black"

var p2 = new Sub()
console.log(p2.colors) //"red, blue, green, black"

如上,我們通過call()方法借調(diào)了超類的構(gòu)造函數(shù),實(shí)際上是在新創(chuàng)建的Sub實(shí)力環(huán)境下調(diào)用了Super構(gòu)造函數(shù)。這樣,就會(huì)在新Sub對(duì)象上執(zhí)行Super()函數(shù)中定義的所有對(duì)象初始化代碼,結(jié)果Sub的每個(gè)實(shí)例都會(huì)有自己的colors屬性的副本。

相對(duì)于原型鏈而言,借用構(gòu)造函數(shù)有一個(gè)很大的優(yōu)勢(shì),可以在子類型構(gòu)造函數(shù)中向超類型構(gòu)造函數(shù)傳遞參數(shù)。

function Super(name) {
    this.name = name
}
function Sub() {
    Super.call(this, "Nicholas")
    this.age = 29
}

var p = new Sub()
console.log(p.name) //"Nicholas"
console.log(p.age) // 29

以上代碼中的Super只接受一個(gè)參數(shù)name,該參數(shù)會(huì)直接賦給一個(gè)屬性。在Sub構(gòu)造函數(shù)內(nèi)部調(diào)用Super構(gòu)造函數(shù)時(shí),實(shí)際上是為Sub的實(shí)例設(shè)置了name屬性。為了確保Super構(gòu)造函數(shù)不會(huì)重寫子類型的屬性,可以在調(diào)用超類型構(gòu)造函數(shù)后,再添加應(yīng)該在子類型中定義的屬性。

問題:利用借用構(gòu)造函數(shù)也會(huì)有一些問題,方法都在構(gòu)造函數(shù)中定義,因此函數(shù)服用就無從談起。而且超類型原型對(duì)象中定義的方法,對(duì)子類型而言也是不可見的。

7. 組合繼承

組合繼承的基本思想:將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊,從而發(fā)揮二者之長(zhǎng)的一種繼承模式。
思路:使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,通過借用構(gòu)造函數(shù)是實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

function Super(name) {
    this.name = name
    this.colors = ["red", "blue", "yellow"]
}

Super.prototype.sayName = function() {
    console.log(this.name)
}

function Sub(name, age) {
    Super.call(this, name)
    this.age = age
} 

//繼承方法
Sub.prototype = new Super()
Sub.prototype.constructor = Sub
Sub.prototype.sayAge = function() {
    console.log(this.age)
}

var p1 = new Sub("Nicholas", 29)
p1.colors.push("black")
console.log(p1.colors) //"red, blue, green, black"
p1.sayName() //"Nicholas"
p1.sayAge() //29

var p2 = new Sub("Greg", 27)
console.log(p2.colors) //"red, blue, green"
p2.sayName() //"Greg"
p2.sayAge() //27

在上面這個(gè)例子中,Super構(gòu)造函數(shù)定義了兩個(gè)屬性:name和colors。Super的原型定義了一個(gè)方法sayName()。Sub構(gòu)造函數(shù)在調(diào)用Super構(gòu)造函數(shù)時(shí)傳入了name參數(shù),緊接著又定義了它自己的屬性age。然后將Super的實(shí)例賦值給Sub的原型對(duì)象,然后又在該新原型上定義了方法sayAge()。這樣Sub構(gòu)造函數(shù)不同的實(shí)例分別擁有自己的屬性,又可以使用相同的方法了。

8. 原型式繼承

原型式繼承的想法時(shí)借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象,同時(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ù),然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型, 最后返回了這個(gè)臨時(shí)類型的一個(gè)新實(shí)例。本質(zhì)上,object()對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制。

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
}

var p1 = object(person)
p1.name = "Greg"
p1.friends.push("Rob")

var p2 = object(person)
p2.name = "Linda"
p2.friends.push("Barbie")

console.log(person.friends) //"Shelby, Court, Van, Rob, Barbie"

以上這種繼承方式要求你必須有一個(gè)對(duì)象作為另一個(gè)對(duì)象的基礎(chǔ)。如果有這么一個(gè)對(duì)象的話,可以把它傳給object()函數(shù),然后再根據(jù)具體需求對(duì)得到的對(duì)象加以修改即可。在上面例子中,person對(duì)象作為基礎(chǔ)對(duì)象,然后傳入到object(),然后該函數(shù)就會(huì)返回一個(gè)新對(duì)象。這個(gè)新對(duì)象將person作為原型,所以它的原型中就包含一個(gè)基本類型值屬性和一個(gè)引用類型值屬性。這意味著person.friends不僅屬于person所有,而且也會(huì)被p1和p2共享。實(shí)際上相當(dāng)于創(chuàng)建了person對(duì)象的兩個(gè)副本。

ECMAScript5通過新增object.create()方法規(guī)范化了原型式繼承。這個(gè)方法接受兩個(gè)參數(shù):一個(gè)用作新對(duì)象原型的對(duì)象和一個(gè)為新對(duì)象定義額外屬性的對(duì)象。在傳入一個(gè)參數(shù)的情況下,Object.create()與object()方法行為相同。

后面還有寄生式繼承和寄生組合繼承....表示看不下去了,前面這幾個(gè)已經(jīng)夠用, 有時(shí)間再學(xué)習(xí)下~

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89411.html

相關(guān)文章

  • 重溫基礎(chǔ)】15.JS對(duì)象介紹

    摘要:構(gòu)造函數(shù)通常首字母大寫,用于區(qū)分普通函數(shù)。這種關(guān)系常被稱為原型鏈,它解釋了為何一個(gè)對(duì)象會(huì)擁有定義在其他對(duì)象中的屬性和方法。中所有的對(duì)象,都有一個(gè)屬性,指向?qū)嵗龑?duì)象的構(gòu)造函數(shù)原型由于是個(gè)非標(biāo)準(zhǔn)屬性,因此只有和兩個(gè)瀏覽器支持,標(biāo)準(zhǔn)方法是。 從這篇文章開始,復(fù)習(xí) MDN 中級(jí)教程 的內(nèi)容了,在初級(jí)教程中,我和大家分享了一些比較簡(jiǎn)單基礎(chǔ)的知識(shí)點(diǎn),并放在我的 【Cute-JavaScript】系...

    booster 評(píng)論0 收藏0
  • 重溫基礎(chǔ)】12.使用對(duì)象

    摘要:本文是重溫基礎(chǔ)系列文章的第十二篇。注意對(duì)象的名稱,對(duì)大小寫敏感。基礎(chǔ)用法第一個(gè)參數(shù)是目標(biāo)對(duì)象,后面參數(shù)都是源對(duì)象。用途遍歷對(duì)象屬性。用途將對(duì)象轉(zhuǎn)為真正的結(jié)構(gòu)。使用場(chǎng)景取出參數(shù)對(duì)象所有可遍歷屬性,拷貝到當(dāng)前對(duì)象中。類似方法合并兩個(gè)對(duì)象。 本文是 重溫基礎(chǔ) 系列文章的第十二篇。 今日感受:需要總結(jié)下2018。 這幾天,重重的感冒發(fā)燒,在家休息好幾天,傷···。 系列目錄: 【復(fù)習(xí)資料...

    garfileo 評(píng)論0 收藏0
  • 重溫基礎(chǔ)】4.函數(shù)

    摘要:本文是重溫基礎(chǔ)系列文章的第四篇。系列目錄復(fù)習(xí)資料資料整理個(gè)人整理重溫基礎(chǔ)語(yǔ)法和數(shù)據(jù)類型重溫基礎(chǔ)流程控制和錯(cuò)誤處理重溫基礎(chǔ)循環(huán)和迭代本章節(jié)復(fù)習(xí)的是中的基礎(chǔ)組件之一,函數(shù),用來復(fù)用特定執(zhí)行邏輯。箭頭函數(shù)不能使用命令,即不能用作函數(shù)。 本文是 重溫基礎(chǔ) 系列文章的第四篇。今日感受:常懷感恩之心,對(duì)人對(duì)己。 系列目錄: 【復(fù)習(xí)資料】ES6/ES7/ES8/ES9資料整理(個(gè)人整理) 【重溫基...

    maxmin 評(píng)論0 收藏0
  • 重溫基礎(chǔ)】instanceof運(yùn)算符

    摘要:需要測(cè)試的函數(shù)構(gòu)造函數(shù)即用運(yùn)算符來檢測(cè)是否存在參數(shù)的原型鏈。區(qū)別只能用來判斷對(duì)象函數(shù)和數(shù)組,不能用來判斷字符串和數(shù)字等用于判斷一個(gè)表達(dá)式的原始值,返回一個(gè)字符串。一般返回結(jié)果有函數(shù)數(shù)組,對(duì)象。 最近開始在整理ES6/ES7/ES8/ES9的知識(shí)點(diǎn)(已經(jīng)上傳到 我的博客 上),碰到一些知識(shí)點(diǎn)是自己已經(jīng)忘記(用得少的知識(shí)點(diǎn)),于是也重新復(fù)習(xí)了一遍。 這篇文章要復(fù)習(xí)的 instanc...

    jimhs 評(píng)論0 收藏0
  • 重溫JS基礎(chǔ)--引用類型(三)

    摘要:今天把接下來引用類型中的一些內(nèi)容全部記錄完畢基本包裝類型為了便于操作基本類型值,還提供了種特殊的引用類型。這三種類型具有與各自的基本類型響應(yīng)的特殊行為。重寫后的返回對(duì)象表示的數(shù)值類型,另外兩個(gè)方法則返回字符串形式的數(shù)值。 今天把接下來引用類型中的一些內(nèi)容全部記錄完畢~ 基本包裝類型 為了便于操作基本類型值,JavaScript還提供了3種特殊的引用類型:Boolean, Number,...

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

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

0條評(píng)論

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