js 繼承

Object.create()實現(xiàn)經(jīng)典繼承

const person = {
  isHuman: false,
  printIntroduction: function () {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"

Object.prototype.toString.call(me) // "[object Object]"

me和person都是Object對象,me繼承了person的所有屬性。

看看Object.create()的Polyfill

if (typeof Object.create !== "function") {
    Object.create = function (proto, propertiesObject) {
        if (typeof proto !== 'object' && typeof proto !== 'function') {
            throw new TypeError('Object prototype may only be an Object: ' + proto);
        } else if (proto === null) {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
        }

        if (typeof propertiesObject != 'undefined') {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
        }

        function F() {}
        F.prototype = proto;

        return new F();
    };
}

Object.create()返回一個新的對象,這個對象的prototype指向proto

ES5

function Person(name) {
  this.name = name
}

Person.prototype.sayHello = function() {
  console.log(this.name + ' say: hello')
}

function Teacher(subject) {
  Person.call(this)
  this.subject = this.subject
}

console.log(Teacher.prototype.constructor) // [Function: Teacher]
console.log(Teacher.prototype instanceof Person) // false

Teacher.prototype = Object.create(Person.prototype)

console.log(Teacher.prototype instanceof Person) // true
console.log(Teacher.prototype.constructor) // [Function: Person]

Teacher.prototype.constructor = Teacher 

將父類原型指向子類

function inheritPrototype(subType, superType){
  var prototype = Object.create(superType.prototype); // 創(chuàng)建對象,創(chuàng)建父類原型的一個副本
  prototype.constructor = subType;                    // 增強(qiáng)對象,彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor 屬性
  subType.prototype = prototype;                      // 指定對象,將新創(chuàng)建的對象賦值給子類的原型
}

ES6類繼承extends

extends關(guān)鍵字主要用于類聲明或者類表達(dá)式中,以創(chuàng)建一個類,該類是另一個類的子類。其中constructor表示構(gòu)造函數(shù),一個類中只能有一個構(gòu)造函數(shù),有多個會報出SyntaxError錯誤,如果沒有顯式指定構(gòu)造方法,則會添加默認(rèn)的 constructor方法,使用例子如下。

class Rectangle {
    // constructor
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
    
    // Getter
    get area() {
        return this.calcArea()
    }
    
    // Method
    calcArea() {
        return this.height * this.width;
    }
}

const rectangle = new Rectangle(10, 20);
console.log(rectangle.area);
// 輸出 200

-----------------------------------------------------------------
// 繼承
class Square extends Rectangle {

  constructor(length) {
    super(length, length);
    
    // 如果子類中存在構(gòu)造函數(shù),則需要在使用“this”之前首先調(diào)用 super()。
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }
}

const square = new Square(10);
console.log(square.area);
// 輸出 100

extends繼承的核心代碼如下,其實現(xiàn)和上述的inheritPrototype方式一樣

function _inherits(subType, superType) {
  
    // 創(chuàng)建對象,創(chuàng)建父類原型的一個副本
    // 增強(qiáng)對象,彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor 屬性
    // 指定對象,將新創(chuàng)建的對象賦值給子類的原型
    subType.prototype = Object.create(superType && superType.prototype, {
        constructor: {
            value: subType,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    
    if (superType) {
        Object.setPrototypeOf 
            ? Object.setPrototypeOf(subType, superType) 
            : subType.__proto__ = superType;
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 繼承6種套餐 參照紅皮書,JS繼承一共6種 1.原型鏈繼承 核心思想:子類的原型指向父類的一個實例 Son.pro...
    燈不梨喵閱讀 3,258評論 1 2
  • 問題1: apply、call 、bind有什么作用,什么區(qū)別 apply/call/bind 問題2: 以下代碼...
    DCbryant閱讀 331評論 0 0
  • 用過 React的讀者知道,經(jīng)常用 extends繼承 React.Component: React github...
    grain先森閱讀 8,650評論 3 41
  • 經(jīng)典的繼承法有何問題 看一下報錯信息 按照原型鏈回溯規(guī)則,Date的所有原型方法都可以通過MyDate對象的原型鏈...
    Perity閱讀 1,593評論 0 50
  • 一、原型鏈 學(xué)過java的同學(xué)應(yīng)該都知道,繼承是java的重要特點之一,許多面向?qū)ο蟮恼Z言都支持兩種繼承方式:接口...
    grain先森閱讀 1,482評論 0 39

友情鏈接更多精彩內(nèi)容