強化原型(二)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章