看一个常见的组合继承的实现方式,代码如下:
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的写法。