关于修正构造器

216 阅读1分钟

看一个常见的组合继承的实现方式,代码如下:

function Animal(name) {
    this.name = name || '';
    console.log('Animal called.');
}
Animal.prototype.showName = function() {
    console.log('Name is: ', this.name);
}
function Cat(name, age) {
    Animal.call(this, name);
    this.age = age || 1;
    console.log('Cat called.');
}
Cat.prototype = new Animal();
// Cat.prototype.constructor = Cat;    // 注释掉修正constructor方法的指向的这一行
Cat.prototype.showAge = function() {
    console.log('Age is: ', this.age);
}

var cat = new Cat('meow', 3);
console.log(cat.name);    // meow
cat.showName();          // Name is: meow
console.log(cat.age);    // 3
cat.showAge();           // Age is: 3

可以看到,继承的效果依然是达到了。应该是能继承。但是注释掉的这行代码的意义是什么呢?为什么大部分的实现方式中都建议我们修正这个constructor的指向呢?

接着刚刚的代码来看:

cat.__proto__.constructor  // 这个属性指向的应该是 Animal 构造函数,如果我们之前修正了constructor的指向的话,那么这里才会真的指向到 Cat 的构造函数

// 假设我们想要构造一个新的实例cat2,并且我们不知道对应的构造函数的名称是什么,不过好在我们刚刚已经有一个实例cat了
var cat2 = new cat.__proto__.constructor();  // Animal called (这里只有Animal的构造函数被调用了)
cat2.age;    // undefined  (因为在Animal构造函数中不存在age属性)

我承认这种场景比较少见。但是,万一有呢?所以我的建议是,我们应该保留这种修正constructor的写法。