《深入理解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 的。