组合继承方式 与 寄生组合式继承

本文探讨了JavaScript中实现继承的两种方式:组合继承和寄生组合继承。组合继承通过结合构造函数和原型链的方式解决了继承中的一些问题,如属性共享和无法传递参数等。而寄生组合继承则进一步优化了这一过程,避免了不必要的构造函数调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组合继承方式解决了
1. 来自原型继承带来的共享数据问题
2. 构造函数不能传第参数问题

function SuperType(name) {
    this.name = name;
    this.colors = ["red","blue","green"];
}
SuperType.prototype.sayname = function(){
    console.log(this.name);
};
function SubType(name,age) {
    SuperType.call(this,name);                           // 第二次调用 SuperType  
    this.age = age;
}
SubType.prototype = new SuperType();            // 第一次调用 SuperType
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    console.log(this.age);
};
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
console.log(instance1.colors);    // red blue green blcak
instance1.sayName();    // "Nicholas"
instance1.sayAge();    // 29

var instance2 = new SubType("Greg",27);
console.log(instance2.colors);    // red blue green
instance2.sayName();    // "Greg"
instance2.sayAge();    // 27

第一次调用 SuperType 构造函数时,SubType.prototype 会得到两个属性:name和colors;它们都是 SuperType的实例属性,只不过继承后位于SubType的原型中。当调用SubType构造函数时,又会调用一次 SuperType 构造函数,这一次又在新对象上创建了实例属性name和colors。



寄生组合式继承方式可以解决两次调用父类的构造函数调用
function object(o) {
    function F(){};
    F.prototype = o;
    return new F();
}
function inheritPrototype(subType,superType) {
    var prototype = object(superType.prototype);   // 返回父类的原型指针
    prototype.constructor = subType;                     // 将父类的原型指针构造指针指向子类  
    subType.prototype = prototype;                        // 将子类原型指针指向父类的原型
}
function SuperType(name) {
    this.name = name;
    this.colors = ["red","blue","green"];
}
SuperType.prototype.sayname = function(){
    console.log(this.name);
};
function SubType(name,age) {
    SuperType.call(this,name);
    this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function() {
    console.log(this.age);
}
var instances = new SubType("xue",30);
instances.sayname();





### JavaScript 不同继承模式的区别 #### 组合式继承 组合式继承利用 `call` 或者 `apply` 来继承父类构造函数的内容,并通过设置子类原型为父类的一个新实例来获取父类的方法。这种方式能够使子类既获得父类的属性又得到其方法。 ```javascript function Parent(name) { this.name = name; } Parent.prototype.sayName = function () { return this.name; }; function Child() {} // 使用 call 方法让 Parent 的构造器作用于新的 Child 实例上 Child.prototype = new Parent('default'); // 这里创建了一个 Parent 的实例作为 Child 原型 Child.prototype.constructor = Child; // 修正 constructor 属性指向 var childInstance = new Child(); console.log(childInstance.sayName()); // 输出: default ``` 这种做法存在一个问题,就是当需要传递参数给父级构造函数时会变得复杂,因为每次都会调用两次父类构造函数——一次是在初始化子类的时候,另一次则是为了建立原型链接[^2]。 #### 寄生组合继承 为了避免上述问题,在寄生组合继承中只会在必要时候调用一次父类构造函数。具体来说,不是简单地把整个父类实例赋值给子类的 prototype ,而是仅复制那些必要的部分到一个新的对象上去,再把这个新对象设为子类的 prototype 。这使得我们可以更加灵活地控制哪些特性应该被共享或独立出来。 ```javascript function inheritPrototype(subType, superType){ let prototype = Object.create(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } inheritPrototype(Child, Parent); let childInst = new Child(); console.log(childInst instanceof Parent); // true ``` 这种方法有效地解决了重复调用父类构造函数的问题,同时也保持了原有功能不变[^4]。 #### ES6 中的 `extends` 关键字 随着 ECMAScript 6 (ES6) 的推出,JavaScript 提供了一种更为直观的方式来处理类之间的关系 —— 即使用 `class` `extends` 关键字来进行面向对象编程中的继承操作。它简化了许多传统方式下的繁琐过程,并提供了更好的可读性维护性。 ```javascript class Animal { constructor(sound) { this.sound = sound; } makeSound() { console.log(`The animal makes a ${this.sound}`); } } class Dog extends Animal { bark() { console.log("Woof!"); } // 调用父类构造函数 constructor(){ super('bark'); } } const myDog = new Dog(); myDog.makeSound(); // The animal makes a bark myDog.bark(); // Woof! ``` 这里的关键在于 `super()` 函数的应用;它允许我们在子类内部访问调用来自父类的方法属性。此外,由于语法糖的存在,开发者不再需要显式管理复杂的原型链结构,从而降低了出错的可能性[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值