组合继承(combination inheritance)
* 有时也叫"伪经典继承",指的是将原型链实现继承和借用构造函数技术和二为一.
* 思路:使用原型链实现对原型属性和方法的继承,而通过街工构造函数实现实例属性的继承.
* 既通过原型上定义的方法实现了函数复用,又能保证每个实例都有自己的属性.

function SuperType(name) {
this.name = name;
this.color = ['red', 'green', 'yellow'];
}

SuperType.prototype.sayName = function () {
console.log(this.name);
};

function SubType(name, age) {
//借用构造函数继承属性
SuperType.call(this, name);
this.age = age;
}

//用原型来继承方法
SubType.prototype = new SuperType();
//SubType.prototype.constructor = SubType;
Object.defineProperty(SubType.prototype, 'constructor', {
value: SubType,
enumerable: false
});

SubType.prototype.sayAge = function () {
console.log(this.age);
};

var instance = new SubType("Sub1", 20);
console.log(instance);
instance.color.push("black");
console.log(instance.color);//["red", "green", "yellow", "black"]
delete instance.color;
console.log(instance.color);//删除之后color变成SuperType的实例的属性
instance.sayName();//Sub1
instance.sayAge();//20
instance.color.push("deeppink");//当前实例没有color属性.所以添加到了SuperType的color上
/*
*__proto__: SuperType
name: undefined
color: (4) ["red", "green", "yellow", "deeppink"]
*/
console.log(instance.color);// ["red", "green", "yellow", "deeppink"]
var instanceSup = new SuperType();//新创建一个SuperType的实例,检测引用类型color是否受实例影响 ,是否还有原型链实现继承的问题
console.log(instanceSup.color);//["red", "green", "yellow"] 不受影响

var instance2 = new SubType("Sub2", 20);
console.log(instance2.color);//["red", "green", "yellow"] 因为这个color是SubType的实例新创建的属性,将原来的color覆盖了所以不受影响
delete instance2.color;//将SubType的实例上的删除,再搜索就会找到SuperType上的color属性
console.log(instance2.color);//["red", "green", "yellow", "deeppink"] 已经受instance影响,instance改变了SuperType的color属性,原型对象上的属性是所有实例共享的
instance2.sayName();//Sub2
instance2.sayAge();//20

官方:

  • 当代码执行到SubType.prototype = new SuperType();时会调用以此SuperType构造函数,SubType.prototype会得到两个属性name和color;他们都是SuperType的实例属性,不过现在位于SubType的原型中.
  • 当代码执行SuperType.call(this, name);时,调用SuperType构造函数这次在SubType原型中创建了实例属性name和color.
  • 于是,这两个属性就屏蔽了原型中的两个同名属性,在操作name和color就是在SubType的实例属性上操作不影响SuperType.(不在SubType的实例上删除name或color属性,删除了,再获取就是SuperType上的属性了,是被SuperType的实例共享的);
  • 上面就是组合继承实现的原理,但问题也暴露出来了,无论什么情况下,会调用两次SuperType构造函数,虽然字类最终会包含超类型对象的全部实例,但我们不得不再调用子类型构造函数时重写这些属性.
  • 解决这一问题的方法: 寄生组合式继承