第一种 原型链继承

  1. function Parent1() {
  2. this.name = 'parent1';
  3. this.play = [1, 2, 3]
  4. }
  5. function Child1() {
  6. this.type = 'child1';
  7. }
  8. // ------- 这里通过修改原型链继承
  9. Child1.prototype = new Parent1();
  10. console.log(new Child1());
  11. var s1 = new Child1()
  12. var s2 = new Child1()
  13. s1.play.push(4)
  14. console.log(s1.play, s2.play) // [1,2,3,4] [1,2,3,4]

缺点:原型链方案存在的缺点:多个实例对引用类型的操作会被篡改。

第二种 构造函数继承

  1. function SuperType(){
  2. this.color=["red","green","blue"];
  3. }
  4. function SubType(){
  5. // ----- 继承自SuperType
  6. SuperType.call(this);
  7. }
  8. var instance1 = new SubType();
  9. instance1.color.push("black");
  10. alert(instance1.color);//"red,green,blue,black"
  11. var instance2 = new SubType();
  12. alert(instance2.color);//"red,green,blue"

核心代码是SuperType.call(this),创建子类实例时调用SuperType构造函数,于是SubType的每个实例都会将SuperType中的属性复制一份。
缺点:

  • 只能继承父类的实例属性和方法,不能继承原型属性/方法
  • 无法实现复用,每个子类都有父类实例函数的副本,影响性能

    第三种 组合继承(原型链+构造函数)

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

function SubType(name, age){ // 继承属性 // 第二次调用SuperType() SuperType.call(this, name); this.age = age; }

// 继承方法 // 构建原型链 // 第一次调用SuperType() SubType.prototype = new SuperType(); // 重写SubType.prototype的constructor属性,指向自己的构造函数SubType 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

  1. 缺点:属性在原型链上有叠加,删除当前实例的属性,但是原型链上还有。
  2. <a name="FXUhS"></a>
  3. # 第四种:原型式继承
  4. ```bash
  5. // 利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型
  6. function object(obj){
  7. function F(){}
  8. F.prototype = obj;
  9. return new F();
  10. }

缺点:

  • 原型链继承多个实例的引用类型属性指向相同,存在篡改的可能。
  • 无法传递参数

    第五种:寄生式继承

    使用原型式继承可以获得一份目标对象的浅拷贝,然后利用这个浅拷贝的能力再进行增强,添加一些方法,这样的继承方式就叫作寄生式继承。
    虽然其优缺点和原型式继承一样,但是对于普通对象的继承方式来说,寄生式继承相比于原型式继承,还是在父类基础上添加了更多的方法。那么我们看一下代码是怎么实现 ```bash let parent5 = { name: “parent5”, friends: [“p1”, “p2”, “p3”], getName: function() { return this.name; } };

function clone(original) { // 使用原型式继承可以获得一份目标对象的浅拷贝,然后利用这个浅拷贝的能力再进行增强 let clone = Object.create(original); clone.getFriends = function() { return this.friends; }; return clone; }

let person5 = clone(parent5);

console.log(person5.getName()); console.log(person5.getFriends());

  1. <a name="n5TIf"></a>
  2. # 第六种:寄生组合式继承
  3. ```bash
  4. function inheritPrototype(subType, superType){
  5. var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
  6. prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
  7. subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
  8. }
  9. // 父类初始化实例属性和原型属性
  10. function SuperType(name){
  11. this.name = name;
  12. this.colors = ["red", "blue", "green"];
  13. }
  14. SuperType.prototype.sayName = function(){
  15. alert(this.name);
  16. };
  17. // 借用构造函数传递增强子类实例属性(支持传参和避免篡改)
  18. function SubType(name, age){
  19. SuperType.call(this, name);
  20. this.age = age;
  21. }
  22. // 将父类原型指向子类
  23. inheritPrototype(SubType, SuperType);
  24. // 新增子类原型属性
  25. SubType.prototype.sayAge = function(){
  26. alert(this.age);
  27. }
  28. var instance1 = new SubType("xyc", 23);
  29. var instance2 = new SubType("lxy", 23);
  30. instance1.colors.push("2"); // ["red", "blue", "green", "2"]
  31. instance1.colors.push("3"); // ["red", "blue", "green", "3"]


第七种 es6 extends super

  1. class A {}
  2. class B extends A {
  3. constructor() {
  4. super(); // ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错。
  5. }
  6. }

注:在 constructor 中必须调用 super 方法,因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工,而 super 就代表了父类的构造函数。super 虽然代表了父类 A 的构造函数,但是返回的是子类 B 的实例,即 super 内部的 this 指的是 B,因此 super() 在这里相当于 A.prototype.constructor.call(this, props)
执行父类的constructor,但是绑定的this是当前子类的。