一起手寫吧!ES5和ES6的繼承機制!


原型

執行代碼var o = new Object();

此時o對象內部會存儲一個指針,這個指針指向了Object.prototype,當執行o.toString()等方法(或訪問其他屬性)時,o會首先查看自身有沒有該方法或屬性,如果沒有的話就沿着內部存儲的指針找到Object.prototype對象,然后查看Object.prototype對象是否有對應名稱的方法或屬性,如果有就調用Object.prototype的方法或屬性。

我們把這個指針叫做o對象的原型。

ES3規范中定義了Object.prototype.isPrototypeOf()方法,該方法可以判斷某個對象是不是另一個對象的原型。Object.prototype.isPrototypeOf(o)返回true值可以確定Object.prototype就是o對象的原型。

在ES3規范中,不能直接讀取o對象的原型,也就是o對象的原型看不見摸不着的。ES5.1規范定義了Object.getPrototypeOf()方法,通過該方法可以獲取對象的原型。我們可以通過Object.getPrototypeOf(o) === Object.prototype再次驗證Object.prototype就是o對象的原型。

ES6規范更加直接,為對象添加了一個__proto__屬性,通過這個屬性就可以獲得對象的原型,所以在支持__proto__的瀏覽器中,o.__proto__ === Object.prototype也會返回true。

當我們執行var x = new X();時,瀏覽器會執行x.__proto__ = X.prototype,會將實例化對象的原型設置為對應的類的prototype對象,這一點很重要。

原型鏈 

我們執行如下代碼:

function Person(){};
var p = new Person();

p.__proto__指向了Person.prototype,Person.prototype的原型是Person.prototype.__proto__,其指向了Object.prototype,Object.prototype.__proto__為null。

通過__proto__向上追蹤形成了如下的鏈式結構:

p -> Person.prototype -> Object.prototype -> null

這一原型的鏈式結構就叫做原型鏈。Object.prototype的原型是null,也就是說Object.prototype沒有原型。

JavaScript 對象有一個指向一個原型對象的鏈。當試圖訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依此層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾。

JavaScript中的繼承是通過原型實現的,雖然在ES6中引入了class關鍵字,但是它只是原型的語法糖,JavaScript繼承仍然是基於原型實現的。 

 

ES5寄生組合繼承 (業內比較提倡的方法)

即通過借助構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。
其背后的基本思路是:不必為了指定子類型的原型而調用超類型的構造函數,我們所需要的無非就是超類型原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型。
function inserit(son, father) {
    var obj = Object.create(father.prototype);
    son.prototype = obj;
    obj.constructor = son
}

function SuperType(name, colors) {
    this.name = name;
    this.colors = colors;
}
SuperType.prototype.sayName = function () {
    return this.name;
}

function SubType(job, name, color) {
    SuperType.call(this, name, color);
    this.job = job;
}
//核心方法
inserit(SubType, SuperType);
SubType.prototype.sayjob = function () {
    return this.job;
}
var instance = new SubType("doctor", "John", ["red", "green"]);
console.log(instance.sayjob(), instance.sayName()) //doctor,John

ES6繼承

ES6支持通過類來實現繼承,方法比較簡單,代碼如下

class Point {
    constructor(x, y) {
        this.x = x
        this.y = y
    }
    
    toString() {
        return this.x + '' + this.y
    }
}

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y) //調用父類的constructor(x, y)
        this.color = color
    }
    
    toString() {
        return this.color + ' ' + super.toString() // 調用父類的toString()
    }
}

var colorPoint = new ColorPoint('1', '2', 'red')

console.log(colorPoint.toString())  // red 12

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM