《深入理解ES6》阅读随笔
Super 的应用
在实例化对象以后,如果还想修改对象的方法,可以这么操作:
let cat = {
sayHello() {
return "cat";
},
};
let dog = {
sayHello() {
return "dog";
},
};
let animal = {
sayHello() {
return "type:" + Object.getPrototypeOf(this).sayHello.call(this);
},
};
Object.setPrototypeOf(animal, cat);
console.log(animal.sayHello()); // 输出 cat
Object.setPrototypeOf(animal, dog);
console.log(animal.sayHello()); // 输出 dog
这里使用 Object.getPrototypeOf(this) 来处理,虽然可以解决问题,但是看着比较臃肿,不易理解。此时可以使用 super 来达到同样的目的:
let newAniaml = {
sayHello() {
return "type:" + super.sayHello();
},
};
Object.setPrototypeOf(newAniaml, cat);
console.log(newAniaml.sayHello()); // 输出 cat
Object.setPrototypeOf(newAniaml, dog);
console.log(newAniaml.sayHello()); // 输出 dog
使用 super 指向正确原型,代码量既少,而且理解起来也更容易一些。
Super 能解决的问题
接着上面的例子,如果先更改原型指向,再使用第一种方式(animal)创建一个新的实例:
Object.setPrototypeOf(animal, dog);
let runner = Object.create(animal)
console.log(runner.sayHello()); // Errer
此处在执行 sayHello 会报异常。因为在创建实例 runner 时,其原型指向 animal,而在 runner 调用 sayHello 时,通过 Object.getPrototypeOf(this) 方法(this 是 runner),又得到了 animal 原型,如此递归下去,栈就溢出了,所以就会报异常。如果改用 super 的方式创建实例:
Object.setPrototypeOf(newAnimal, dog);
let runner = Object.create(newAnimal)
console.log(runner.sayHello()); // 输出 dog
就一切正常了,因为 super 永远会指向正确的原型,在上面的例子中,正确的原型是指向 dog 的。