js实现继承的几种方法

43次阅读

共计 3737 个字符,预计需要花费 10 分钟才能阅读完成。

继承

在 ECMAScript 中继承主要是依靠原型链来实现的。

  • 实现继承的方法

利用原型让一个引用类型继承另一个引用类型的属性和方法

什么是原型链

  • 先要了解构造函数、原型、和实例的关系:

    <font color="red"> 每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例都包含一个指向原型对象的内部指针。</font>
    
  • 实现原型链

    假如原型对象等于另一个类型的实例,此时该原型对象将包含指向另一个原型的指针,相应的另一个原型中也包含着一个指针指向另一个构造函数的指针。这样层层递进,就构成了实例与原型之间的链条。这就是原型链的基本概念。
  • 判断原型和实例的关系
    可以通过两种方式来确定原型和实例之间关系。

    1. 使用 instanceof 操作符,只要用这个操作符来测试实例和原型链中出现的构造函数,结果就一定返回 true。
    alert(instance instanceof Object); //true  
    1. 使用 isprototypeOf()方法,同样只要是原型链中出现过得原型,都可以说是原型链所派生的实例的原型。isportotypeOf()也会返回 true
alert(Object.prototype.isPrototypeOf(instance)); //true

所有引用类型都默认继承了 Object

  1. 原型链存在的问题

    1. 在通过原型来实现继承时,原型实际上会变成另一个类型的实例。原先的实例属性就变成了现在的原型属性了。

      function SuperType(){this.color=["red","blue","green"]
      }
      
      function SubType(){}
      SubType.prototype = new SuperType();// 继承了 SuperType();
      
      var instance1 = new SubType();
      instance1.color.push("black");
      console.log(instance1.color); //"red,blue,green,black"
      
      var instance2 = new SubType();
      console.log(instance2.color); //"red,blue,green,black"
SuperType 构造函数定义了一个 colors 属性,SuperType 的每个实例都会有各自包含自己数组的 color 属性。当 SubType 通过原型链继承了 SuperType 之后,subType.prototype 就变成了 SuperType 的一个实例,因此它也就拥有了自己的 color 属性。那 SubType 的所有实例都会共享这个 color 属性。2. 在创建子类型的实例时,不能向超类型的构造函数中传递参数。

实现继承的方法

1. 借用构造函数

解决原型中包含引用类型所带来的问题的过程中,使用 <font color=”red”> 借用构造函数 </font>(伪造对象或经典继承)来实现继承。主要是通过使用 apply()和 call()方法在新创建的对象上执行构造函数如下:

function SuperType(){this.color=["red","blue","green"]
}

function SubType(){
    // 继承了 SuperType
    SuperType.call(this);
}

var instance1 = new SubType();
instance1.color.push("black");
console.log(instance1.color) //"red, blue,green,black"

var instance2 = new SubType();
console.log(instance2.color) //"red,blue,green"

通过 call()或 apply()方法在新创建的 SubType 实例的环境下调用了 SuperType 构造函数

相对原型链,借用构造函数可以子类型构造函数中向超类型构造函数传递参数如下:

function SuperType(name){this.name=name;}
function SubType(){
    // 继承了 SuperType 同时还传递了参数
    SuperType.call(this,"aa");
    // 实例属性
    this.age=29;
}

var instance = new SubType();
alert(instance.name) // aa
alert(instance.age) //29

### 2. 组合继承
组合继承也叫做 <font color=”red”> 伪经典继承 </font> 将原型链和借用构造函数的技术组合到一块,从而发挥二组之所长的一种继承模式。思路是 <font color=”red”> 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。</font>

function SuperType(name){
    this.name=name;
   this.color = ["red","blue","green"]
};

SuperType.prototype.sayName = function(){alert(this.name)
};

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

// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){alert(this.age);
};

var instance1 = new SubType("aaa",29);
instance1.color.push("black");
alert(instance1.color); //"red,blue,green,black"
instance1.sayName(); //"aaa"
instance1.sayAge(); // 29

 var instance2 = new SubType("ccc",30);
alert(instance2.color); //"red,blue,green"
instance2.sayName(); //"ccc"
instance2.sayAge(); // 30

组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为 JavaScript 中最常用的继承模式。<font color=”red”> 而且 instanceOf 和 isPrototype()也能够识别基于组合继承创建的对象。</font>
### 3. 原型式继承
借用原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

var person = {
    name:"Nicholas",
    friends:["Shelby","court","Van"]
};

var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends) //"Shelby,Count,Van,Rob,Barbie"

Object.create()传递第二个参数

var person = {
    name: "Nicholas",
    friends: ["Shelby","Court","Van"]
}

var anotherPerson = Object.create(person,{
    name: {value: "Greg"}
});

var anotherPerson2 = Object.create(person,{
    name: {value: "blue"}
});
alert(anotherPerson.name) //"Greg"
alert(anotherPerson2.name) //"blue"

Obeject.create()方法 IE9 开始兼容
### 4. 寄生式继承
寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像·真地是它做了所有工作一样返回对象。

function createAnother(original) {var clone = object(original);
    clone.sayHi = function(){alert("hi");
    };
    return clone;
}

var person = {
    name: "Nicholas",
    friends: ["Shelby","Court","Van"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

本文主要是个人摘自《javascript 高级程序设计》用来做个人笔记的, 请大佬们手下留情。

正文完
 0