强化原型(二)

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

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