因爲寫本文時所有是在編輯器中邊寫代碼邊寫感想的,因此,所有思想都寫在代碼註釋裏面了javascript
// 類繼承 //todo.1 extends 關鍵字 class Animal { constructor(name) { this.speed = 0; this.name = name; } run(speed) { this.speed = speed; console.log(`${this.name} runs with speed ${this.speed}`); } } // 若是「派生類」使用constructor函數,則必須在constructor調用this以前使用super來調用被繼承類的constructor // 若是「派生類」沒有使用constructor函數,則默認會生成一個constructor,代碼以下 /** * constructor(...args) { * super(...args) * } */ // 爲何須要super() ? // 由於「派生類(derived constructor)的構造函數與其餘函數之間的區別在於其具備特殊的內部屬性[[ConstructorKind]]:derived」 // 這個屬性會影響new 的行爲; 當經過new執行一個常規函數時,它將建立一個空對象,並將這個空對象賦值給this; // 可是當繼承的constructor執行時,它不會執行此操做,它指望父類的constructor來完成這項工做。所以派生類必須執行super才能執行 // 父類的constructor來完成這項工做,不然this指向的那個對象不會建立,而且程序會報錯! class Rabbit extends Animal { constructor(name, color) { super(name); this.color = color; } } const rabbit = new Rabbit("兔子", "白色"); //todo.2 深刻探究內部原理和[[HomeObject]] // 讓咱們先來看一個例子。 const animal = { name:'Animal', eat() { console.log('animal'); } } const tiger = { __proto__:animal, name:'tiger', eat() { this.__proto__.eat.call(this); } } const youngTiger = { __proto__:tiger, name:'youngTiger', eat() { this.__proto__.eat.call(this); } } tiger.eat(); // animal // youngTiger.eat(); // RangeError: Maximum call stack size exceeded // 爲何會報錯?讓咱們來深刻探究一下 /** * 在youngerTiger.eat中 * this.__proto__.eat.call(this) * 等於 * youngTiger.__proto__.eat.call(this) * 等於 * tiger.eat.call(this) * 在tiger.eat中 * this.__proto__.eat.call(this) * 等於 * youngTiger.__proto__.eat.call(this) * 等於 * tiger.eat.call(this) */ // 解決方案:[[HomeObject]] // 當一個函數被定義爲類或者對象方法時,它的 [[HomeObject]] 屬性就成爲了該對象。 // 而後 super 使用它來解析(resolve)父原型及其方法。 let plant = { name:'Plant', grow() { console.log(`${this.name} growing`); } } let flower = { __proto__:plant, grow() { super.grow(); } } let greenFlower = { __proto__:flower, grow() { super.grow() } } greenFlower.grow();//Plant growing // [[HomeObject]]內置屬性是被綁定到JavaScript對象上的,「方法」由哪一個對象建立,則 // [[HomeObject]]指向哪一個對象,而且[[HomeObject]]一旦建立就是不可變的 // 並且只能被super解析。注意:「方法」不是「函數屬性」, // 「方法」 {method(){}},「函數屬性」{method:function(){}} // 解析,當對象嵌套繼承時,爲了不Maximum call stack size exceeded錯誤, // 咱們可使用super來代替 this.__proto__.method.call(this)方法,前提是 // [[HomeObject]]屬性存在,而且__proto__存在