借用构造函数(伪造对象/经典继承)
*基本思想:在子类型构造函数的内部调用超类型构造函数。
*通过使用apply()和call()方法也可以在(将来)新创建的对象上执行构造函数。
* 相当于在子类型的内部执行了跟超类型身上所有的操作,比如添加属性,方法,实现继承超类型的方法和属性
* 不同于原型链继承的是,子类型不再是超类型的实例,就和名字一样,其余的操作跟创建了一个构造函数一样。
function SuperType() {
this.color = ['red', 'blue', 'black'];
}
SuperType.prototype.sayColor = function () {
console.log(this.color);
};
function SubType() {
//继承SuperType
SuperType.call(this);//call改变函数执行作用域
}
// console.log(Object.getPrototypeOf(SubType.prototype));
let instance = new SubType();
//console.log(Object.getPrototypeOf(instance));
//console.log(instance.constructor);// SubType 继承的原型中的默认属性constructor ,原型中的constructor属性指向函数本身。(SubType)
console.log(instance);
instance.color.push("green");
console.log(instance.color);//["red", "blue", "black", "green"]
let instance2 = new SubType();
console.log(instance2.color);//["red", "blue", "black"]
/*problem : call只实现 在子类型的构造函数内部执行了超类型构造函数的创建过程,相当于创建了一个和超类型一样的类
* 但是超类型在原型链上的方法并没有被子类型拿到,
* console.log(instance.sayColor());//instance.sayColor is not a function
* 想要拿到需要原型上的方法,就要配合原型实现继承完成,或者这有一个不好看,好理解的方法:
* */
for (var i in SuperType.prototype) {
// console.log(i);//satColor
// console.log(SuperType.prototype[i]);//ƒ () {
//console.log(this.color);
//}
SubType.prototype[i] = SuperType.prototype[i];
}
//再来个原型实现继承,继承SubType
// function Proto() {
// }
// Proto.prototype = new SubType();
// var p = new Proto();
// p.color.push("bad");
// console.log(p);
// console.log(p.color);
// var pp = new Proto();
// console.log(pp.color);
// var instance3 = new SubType();
// delete instance3.color;//删除color属性就没了undefined,
// console.log(instance3.color);//不受影响,通过原型继承的Proto的实例改变了color属性不会影响到别的,受影响的是根据Proto创建的新实例
//原型实现继承的问题解决了,同时构造函数还可以传入参数,but
/*借用构建函数继承的问题:
* 方法都在构造函数中定义,因此复用就无从谈起.
* 而且在草类型中定义方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式.
* 考虑到这些问题,借用构建函数的技术很少单独使用.
*
* 解决这一问题,有了 组合实现继承