欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript实现继承的六种方式实例讲解

程序员文章站 2022-08-04 11:40:52
JavaScript实现继承的六种方式实例讲解 1.借用构造函数 借用构造函数实现继承,就是在子类型构造函数内部调用父类型构造函数,使用apply()和call()方法将父类型...

JavaScript实现继承的六种方式实例讲解

1.借用构造函数

借用构造函数实现继承,就是在子类型构造函数内部调用父类型构造函数,使用apply()和call()方法将父类型的构造函数绑定在子类型上。

function SuperType(){ 
    this.colors = ["red", "blue", "green"]; 
} 
function SubType(){   
    SuperType.call(this);       //继承了 SuperType
} 
var instance1 = new SubType(); 
instance1.colors.push("black"); 
 //instance1实例得到了一个color属性的副本,改变的是instance1这个实例的color属性,而不是其原型对象中的color属性。
alert(instance1.colors);    //"red,blue,green,black" 
var instance2 = new SubType(); 
alert(instance2.colors);    //"red,blue,green"

通过使用apply()或call()方法,实际上是在新创建的SubType实例的环境下调用SuperType构造函数。SubType的每个实例都会具有自己的color属性的副本。

2.原型链继承

依靠原型链来实现继承,就是利用原型让一个引用类型继承另一个引用类型的属性和方法。

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
}

function SubType(){
    this.subproperty = false;
}

SubType.prototype = new SuperType();
//创建 SuperType 的实例,并将该实例赋给SubType.prototype,这样SubType就继承了SuperType。
SubType.prototype.getSubValue = function(){
    return this.subproperty;
}

var instance = new SubType();
//存在于SuperType 的实例中的所有属性和方法,也存在于 SubType.prototype 中了。
alert(instance.getSuperValue());       //true

3.组合继承

组合继承就是将原型链和借用构造函数的技术组合到一起。

使用原型链实现对原型属性和方法的继承;通过借用构造函数来实现对实例属性的继承。这样在原型上定义的方法实现了函数的复用,又能保证每个实例都有自己的属性。

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);       //继承属性     
    this.age = age; 
} 

SubType.prototype = new SuperType(); 
SubType.prototype.constructor = SubType; 
//添加constructor属性是为了弥补重写原型而失去的默认constructor属性。
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
//instance1和instance2这两个实例分别拥有自己的属性,又拥有相同的方法。

4.原型式继承

借助原型可以基于已有的对象创建新对象,而不必因此创建自定义的类型。

function object(o){ 
    function F(){} ;
    F.prototype = o; 
    return new F(); 
}
//在 object()函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例。

var person = { 
    name: "Nicholas", 
    friends: ["Shelby", "Court", "Van"] 
};                  
//person对象作为后续对象的继承,后续的对象在person的基础上根据具体的需求进行修改。

var anotherPerson = object(person); 
//创建的新对象将person作为原型。原型中包含一个基本类型值的属性和一个引用类型值的属性,那么这个引用类型值的属性friends,将会共享给新创建的对象。
anotherPerson.name = "Greg"; 
anotherPerson.friends.push("Rob"); 

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

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

ES5提供了Object.create()方法来实现原型式继承

两个参数:用作新对象原型的对象、为新对象定义其他属性的对象(可选)。

只传入一个参数时,Object.create()方法和object()方法行为相同:

var person = { 
    name: "Nicholas", 
    friends: ["Shelby", "Court", "Van"] 
}; 
var anotherPerson = Object.create(person); 
anotherPerson.name = "Greg"; 
anotherPerson.friends.push("Rob");
console.log(person);

  Object.create()方法的第二个参数与Object.defineProperties()方法的第二个参数格式相同:每个属性都通过自己的描述符定义。重新定义的属性会覆盖原型对象上的同名属性。

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

5.寄生式继承

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

function createAnother(original){ //参数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"
//基于person返回了一个新对象。新对象不仅拥有person的所有属性和方法,同时也拥有自己的sayHi()方法。

6.寄生组合式继承

寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上就是使用寄生式继承来继承超类型的原型,再将结果指定给子类型的原型。

function inheritPrototype(subType, superType){ 
    var prototype = Object(superType.prototype);     //创建对象 
    prototype.constructor = subType;                //增强对象 
    subType.prototype = prototype;                  //指定对象 
} 

函数接受两个参数:子类型和超类型。

第一步:创建超类型原型的一个副本。

第二步:为创建的副本添加属性,这里添加的constructor 属性是为了弥补因重写原型而失去的默认的 constructor 属性。

第三步:将新创建的对象赋值给子类型的原型。

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); 
    this.age = age; 
} 

inheritPrototype(SubType, SuperType); 

SubType.prototype.sayAge = function(){ 
    alert(this.age); 
};