因为写本文时所有是在编辑器中边写代码边写感想的,因此,所有思想都写在代码注释里面了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__存在