组合继承和寄生组合继承的区别

本文介绍了JavaScript中组合继承和寄生组合式继承的概念及实现方式。组合继承通过借用构造函数实现实例属性继承,利用原型链实现方法继承;而寄生组合式继承则解决了前者存在的问题,成为更理想的继承方式。

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

组合继承

核心思想:使用借用构造函数的技术实现实例属性的继承,使用原型链实现原型属性和方法的继承。

function SuperType(name){
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
            alert(this.name);
        };

        function SubType(name, age){  
            SuperType.call(this, name);           //借用构造函数,继承了SuperType,拥有name,colors属性,第一次调用
            this.age = age;                       //自定义实例属性
        }

        SubType.prototype = new SuperType();      //构造原型链,继承原型属性和方法
        SubType.prototype.constructor=SubType;
        SubType.prototype.sayAge = function(){     //向原型中添加方法
            alert(this.age);
        };
        
        var instance1 = new SubType("Nicholas", 29);   //第二次调用
        instance1.colors.push("black");
        alert(instance1.colors);  //"red,blue,green,black"
        instance1.sayName();      //"Nicholas";
        instance1.sayAge();       //29
        
       
        var instance2 = new SubType("Greg", 27);
        alert(instance2.colors);  //"red,blue,green"
        instance2.sayName();      //"Greg";
        instance2.sayAge();       //27

  实际上,使用SubType.prototype = new SuperType();SubType将会继承SuperType实例对象的name,colors属性,虽然name没有被创建

delete instance1.name;
alert(instance1.name);       //undefined,new SuperType()中没有传入实参

  因此造成了一个问题,SubType.prototype上会存在不必要的,多余的属性。如name,colors属性同时存在于SubType.prototype和SubType中。

 

寄生组合式继承

核心思想:用借用构造函数技术继承超类型属性,用inheritPrototype方法继承超类型原型的方法。该方法详细内容可查找相关资料。

该方法的好处在于只调用了一次SuperType构造函数,并且SubType.prototype上没有多余的属性。

该方法是引用类型最理想的继承方式。

 

参考书籍:javascript高级程序设计

 

转载于:https://www.cnblogs.com/pick7/p/5518212.html

### 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、付费专栏及课程。

余额充值