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

資訊專欄INFORMATION COLUMN

重溫JS基礎--繼承

sixleaves / 2320人閱讀

摘要:繼承了如上,我們通過方法借調了超類的構造函數,實際上是在新創建的實力環境下調用了構造函數。組合繼承組合繼承的基本思想將原型鏈和借用構造函數的技術組合到一塊,從而發揮二者之長的一種繼承模式。繼承方法在上面這個例子中,構造函數定義了兩個屬性和。

在ECMAScript中只支持實現繼承,而且實現繼承主要是依靠原型鏈來實現的。

1. 什么是原型鏈

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

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

如上代碼,很好的描述了利用原型鏈進行繼承。Super和Sub兩個構造函數。每個類型分別有一個屬性和一個方法。Sub繼承了Spuer,而繼承時通過創建了Super的實例,并將該實例賦給Sub.prototype實現。這實現的本質是重寫了原型對象。在確立繼承關系后我們又給Sub.prototype上面加了一個新方法。注意現在instance.constructor現在指向的值Super,因為Sub.prototype中的constructor被重寫了。

2. 別忘記默認的原型

我們知道,所有引用類型默認都繼承Object, 而這個繼承也是通過原型鏈實現的。所有函數的默認原型對象都是Object的實例。因此默認原型都會包含一個指向內部的指針,指向Object.prototype。

3. 確定原型和實例的關系

可以通過兩種方式來確定原型和實例之間的關系。第一種是通過instanceof操作符,只要用這個操作符來測試實例與原型鏈中出現過的構造函數,結果就會返回true。

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

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

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

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

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

還有一點需要注意的是,通過原型鏈繼承的時候,不能使用對象字面量的形式創建原型方法。這是因為會重寫原型鏈。

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()
alert(instance.getSuperValue()) //error

如上,Sub繼承了Super,緊接著又將原型替換成了一個對象字面量而導致問題。由于現在的原型包含的是一個Object的實例,而非SuperType的實例,因此我們設想的原型鏈已經被切斷。

5. 原型鏈的問題

使用原型鏈繼承的主要問題還是來自于包含引用類型值得原型。通過原型來實現繼承時,原型實際上會變成另一個類型的實例。于是,原先的實例屬性也就成了現在的原型屬性了。因為原型屬性上是實例共享的,那么就會出現問題。

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"]

原型鏈的第二個問題就是,創建子類型實例時,不能向超類型的構造函數傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數。

6. 借用構造函數

在解決原型對象中包含引用類型值所帶來問題得過程中,使用一種叫做借用構造函數的技術。
基本思想:在子類型構造函數的內部調用超類型構造函數。(函數只不過是在特定環境下執行代碼的對象)因此,可以通過使用apply()call()方法可以在新創建的對象上執行構造函數。

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()方法借調了超類的構造函數,實際上是在新創建的Sub實力環境下調用了Super構造函數。這樣,就會在新Sub對象上執行Super()函數中定義的所有對象初始化代碼,結果Sub的每個實例都會有自己的colors屬性的副本。

相對于原型鏈而言,借用構造函數有一個很大的優勢,可以在子類型構造函數中向超類型構造函數傳遞參數。

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只接受一個參數name,該參數會直接賦給一個屬性。在Sub構造函數內部調用Super構造函數時,實際上是為Sub的實例設置了name屬性。為了確保Super構造函數不會重寫子類型的屬性,可以在調用超類型構造函數后,再添加應該在子類型中定義的屬性。

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

7. 組合繼承

組合繼承的基本思想:將原型鏈和借用構造函數的技術組合到一塊,從而發揮二者之長的一種繼承模式。
思路:使用原型鏈實現對原型屬性和方法的繼承,通過借用構造函數是實現對實例屬性的繼承。

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

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

8. 原型式繼承

原型式繼承的想法時借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型。

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

如上,在object()函數內部,先創建一個臨時性的構造函數,然后將傳入的對象作為這個構造函數的原型, 最后返回了這個臨時類型的一個新實例。本質上,object()對傳入其中的對象執行了一次淺復制。

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"

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

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

后面還有寄生式繼承和寄生組合繼承....表示看不下去了,前面這幾個已經夠用, 有時間再學習下~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89411.html

相關文章

  • 重溫基礎】15.JS對象介紹

    摘要:構造函數通常首字母大寫,用于區分普通函數。這種關系常被稱為原型鏈,它解釋了為何一個對象會擁有定義在其他對象中的屬性和方法。中所有的對象,都有一個屬性,指向實例對象的構造函數原型由于是個非標準屬性,因此只有和兩個瀏覽器支持,標準方法是。 從這篇文章開始,復習 MDN 中級教程 的內容了,在初級教程中,我和大家分享了一些比較簡單基礎的知識點,并放在我的 【Cute-JavaScript】系...

    booster 評論0 收藏0
  • 重溫基礎】12.使用對象

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

    garfileo 評論0 收藏0
  • 重溫基礎】4.函數

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

    maxmin 評論0 收藏0
  • 重溫基礎】instanceof運算符

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

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

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

    kel 評論0 收藏0

發表評論

0條評論

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