面向对象继承遇到的难点
1.原型链的缺点:
- 原型上包含引用类型的属性会被所有实例共享。
- 第二个问题是在创建子类型的实例时,不能向超类型的构造函数传递参数。
提问:
(1)为什么要给超类型构造函数传参数?
function SuperType(){}
function SubType(){}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
不过我们可以看到在借用构造函数中,子类型实例确实可以给超类型构造函数传递参数。
2.借用构造函数的缺点:
- 超类型原型上定义的方法,子类型的实例无法访问。
- 方法都定义在构造函数中,因此无法复用。
提问:
(1)方法都定义在构造函数中,无法复用。该如何理解?
方法定义在构造函数中,实例话多次。
定义在原型方法上实例化一次。
function SuperType(name){
this.name = name;
}
SuperType.prototype.getSuperValue = function(){
console.log(this.name);
}
function SubType(name){
SuperType.call(this,name);
}
var instance1 = new SubType('tianxia');
instance1.getSuperValue(); //TypeError: instance1.getSuperValue is not a function
稍微改造以下就可以打印出结果,同时也证明了方法都定义在构造函数中,因此无法复用。
function SuperType(name){
this.name = name;
this.getSuperValue = function(){
console.log(this.name);
}
}
function SubType(name){
SuperType.call(this,name);
}
var instance1 = new SubType('tianxia666');
instance1.getSuperValue(); //'天下'
那么问题又来了,我在子类型的原型上添加方法不算是复用吗?
不算,因为子类型可以有多个,需要继承超类型。比如我再来一个:
function SubType1(){
SuperType.call(this);
}
这是另一个子类型。
例如:
SubType.prototype.getSubValue = function(){
console.log(this.name);
}
instance1.getSubValue(); //'tianxia666'
之前
SubType.prorotype = new SuperType();
因为这样,继承了超类型的属性和方法,因此在子类型的实例上才可以调用超类型的方法,然而在借用构造函数没有用这种方式继承,因此就无法调用超类型的方法。
3.寄生式继承
提问:
在主要考虑到对象而不是自定义类型和构造函数的情况下,寄生继承也是一种有用的继承模式。前面示例继承模式时使用的object()函数不是必须的;任何能够返回新对象的模式都使用此模式。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
比如:
object.assign();
function object(){
return Object.assign({},{name:'tianxia',colors:['red']})
}
var otherPerson = object();
console.log(otherPerson);
otherPerson.name = 'tianxia666';
console.log(otherPerson);