JS组合继承相比原型链继承的优势

目录

 

原型继承:

原型链继承的问题:

组合继承:


原型继承:

// '父'构造函数
function Father() {
    this.name = 'foo';
    this.family = ['Jack','Tom','James'];
}
Father.prototype.sayName = function () {
  console.log(this.name);
};
Father.prototype.sayFamily = function () {
};
// '子'构造函数
function Child() {
}
// 实现继承
Child.prototype = new Father();
// 看看继承之后的效果
let childInstance1 = new Child();
childInstance1.sayName(); // 'foo'
childInstance1.sayFamily(); // ['Jack','Tom','James']

通过将子构造函数的原型设置为父构造函数实例的方法实现了继承,这就是原型链继承。在这个例子中,子构造函数的实例本身是没有 name 和 family 属性的,这两个属性都是通过原型链在子构造函数的原型上找到的,而子构造函数的原型来自于父构造函数的一个实例。 子构造函数的实例本身也是没有 sayName 和 sayFamily 方法的,沿着原型链查找,子构造函数的原型中也没有这两个方法,再向上查找,这两个方法来自与父构造函数的原型上。

 

原型链继承的问题:

通过这种继承方法,有一个比较明显的问题,我们知道,引用类型的原型属性会被所有的实例共享,那么在上面的例子中,由于子构造函数的原型是父构造函数的实例,所以 family 属性(数组是引用类型)会被子构造函数的所有实例共享。也就是说,当我们修改了子构造函数一个实例上的 family 属性时,会对子构造函数原型上的该属性直接产生影响,从而影响到子构造函数的全部实例。

// 修改subInstance2的属性值,看看会有什么影响
let childInstance2 = new Child();
childInstance2.name = 'bar';
childInstance2.family.push('curry');

childInstance1.sayName(); // 'foo'
childInstance1.sayFamily(); // ['Jack','Tom','James','curry']
childInstance2.sayName(); // 'bar'
childInstance2.sayFamily(); // ['Jack','Tom','James','curry']

我们看到,修改了 childInstance2 的 name 属性(字符串是基础类型),不会对其他实例产生影响,但是当我们修改了 family 属性时,就会造成 childInstance1 的 family 属性也被修改了。这显然会带来很多的麻烦。

 

组合继承:

思路是通过原型链实现对原型属性和方法的继承,但是利用构造函数实现对实例属性的继承,避免属性被共享。

// '父'构造函数
function Father() {
    this.family = ['Jack','Tom','James'];
}
Father.prototype.sayFamily = function () {
  console.log(this.family);
};
// '子'构造函数  
// 这里利用构造函数把父构造函数的属性直接放到子构造函数属性中
function Child() {
    Father.call(this); 
}
// 实现继承
Child.prototype = new Father();
// 看看继承之后的效果
let childInstance1 = new Child();
childInstance1.sayFamily(); // ['Jack','Tom','James']
// 修改subInstance2的属性值,看看会有什么影响
let childInstance2 = new Child();
childInstance2.family.push('curry');

childInstance1.sayFamily(); // ['Jack','Tom','James']
childInstance2.sayFamily(); // ['Jack','Tom','James','curry']

采用组合继承,子构造函数创造出来的实例本身就有 family 属性(构造函数具有的属性和方法都在实例本身),不必再通过原型链向原型查找,也就避免了属性被共享的问题。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值