js(4) 继承

一:使用原型链来实现继承

在介绍原型链之前,要引入构造函数,原型,和实例的关系

构造函数都有一个原型对象,在原型对象中存在一个指向构造函数的指针(constructor),在实例中包含一个指向原型对象的内部指针(prototype)

构建原型链的原理是让一个类型的原型对象等于另一个类型的实例

当使用new 操作符构造实例的时候,实例会拥有构造函数原型中的属性和方法

实现代码如下:

function  SuperType(){
    this.property=true;  
}
//在SuperType的原型上定义了getSuperValue方法 SuperType.prototype.getSuperValue=function(){ return this.property } function SubType(){ this.subproperty=false; }
//让SubType.prototype等于SuperType的实例 SubType.prototype=new SuperType(); SubType.prototype.getSubValue=function(){ return this.subproperty; } var instance=new SubType(); alert(instance.getSuperValue())

继承实现的本质是重写原型对象,代之以一个新类型的实例

二:使用构造函数

这种方法的原理是在子类型构造函数的内部调用超类型构造函数,通过call()或者apply()方法

function SuperType(){

  this.colors=["red","blue","green"]

}
function SubType(){
  SuperType.call(this);
}
var insance1=new SubType();
instance1.colors.push("black");
alert(instancel.colors) //"red blue green black"
var instance2=new Subtype();
alert(instance2.colors)//"red blue green"

使用 call()方法或者 apply()方法,在将来要创建的SubType实例的环境下调用了superType()函数

因为对于call()和apply()方法实际上改变了this的值,对于call或者apply有什么区别呢?

call()及apply()属于函数的方法,使用call()或者apply()可以实现改变this的值,这两个方法的用途是在特定的作用域中调用函数,通过改变this的值实现的

call()和apply()的作用是相同的,但是对于传递参数的方式不同

格式:

call(this,arg1,arg2,arg3.....) 只能以这种方法      apply(this,arg1,arg2,arg3...)或者appjy(this,[arg1,arg2,arg3....])

代码如下:

window.color="red";
var o={color:"blue"};
function  sayColord(){
     alert(this.color)  
}
sayColor();        //red
sayColor.call(this);//red
sayColor(window);//red
sayColor.call(o);//blue //此时函数体内的this对象指向了对象o

 除了call和apply方法之外,还有一个bind()方法,this值会指定到传给bind()函数的值 、

借用构造函数的缺点:在超类型函数中的原型中定义的函数,对于子类型函数是不可见的,如果在构造函数中定义方法,就无法满足函数的复用性,因此很少用借用构造函数来实现继承的效果

为了解决这个问题,我们使用组合继承来实现对于函数方法的继承:

三:组合继承

组合继承的原理是结合原型链和构造函数进行继承:

利用原型链实现对于原型属性和方法的继承,而通过借用构造函数实现对于原型属性和方法的继承,这样就能解决单独利用构造函数产生的不能继承函数方法的问题:

代码如下:

    function SuperType(name){
this.name=name; this.colors=["red","blue","green"] }
//给Subpertype的原型上定义方法 Supertype.prototype.sayName=function(){ alert(this.name); };
//借用构造函数实现继承
//改变了this值,传入了一个参数this.name function SubType(){ SuperType.call(this.name); this.age=age; }
//函数的原型是另一个函数的实例,借用了原型链实现继承
//本身在SubType原型上定义了一个sayAge的方法
//原型链实现的继承,同时继承了Supertype上的sayName方法 SubType.prototype=new SuperType(); SubType.prototype.constructoe=subType; SubType.protoye.sayAge=function(){ alert(this.age); } var instance1=new SubType("Nicholas",29); instance1.colors.push("black"); alert(instance1.colors);// "red","blue","green","black" instancel.sayName(); //"Nicholas" instancel.sayAge(); //29

如上:

在上面的例子中,通过原型链和利用构造函数(改变this值来实现继承)来实现继承

sayAge()方法来自于SubType原型上的方法

sayName()方法来自于SuperType原型上的方法

this.name this.color这两个属性是通过构造函数继承的superType()中的

四:原型式继承

原型式继承的方法是利用object()函数或者ES5中规范的Object.create()方法来规范原型式继承

原理:

将一个对象a作为参数传入object()函数,这个函数会返回一个新对象,这个返回的新对象就会以对象a作为原型来实现继承,从而新对象就会继承对象a中的所有属性和方法;

同时,新对象本身也可以定义自身的新对象和方法;

代码:

 var person={
         name:"Nicholas",
         friends:["Shelby","Court","Van"]
     };
     var anotherPerson=Object.create(person);
alert(anotherPerson.name)//"Nicholas" anotherPerson.name="zhang"; alert(anotherPerson.name);//"zhang"

 当新对象定义的属性和原来的对象的属性同名的时候新对象定义的属性将会覆盖原来对象的属性 

如上:

五:寄生式继承:

寄生式继承的方法是创建一个仅用于封装继承过程的函数:该函数在内部以某种方式来增强对象:

与原型式继承的方式是一致的,不同的是后面用于增强属性的那一部分被封装为了函数部分:

代码部分如下:

function createAnother(original){
    var clone=Object(original)
   //封装函数,增强了sayHi方法
    clone.sayHi=function(){
         alert("hi")
    }
    return clone;
}
var person={
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
}
var  anotherPerson=createAnother(person);
anotherPerson.sayHi();//弹出alert "hi"

  

如上:

六:寄生组合式继承

使用组合式继承会调用两次超类型的构造函数,为了减少调用次数,我们使用计生组合式继承来减少调用次数:

代码如下:

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;
}
function inheritPrototype(subType,superType){
    var prototype=object(superType.prototype);
    prototype.constructor=subType;
    subType.prototype=prototype;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge=function(){
    alert(this.age);
}

 如上:

不必为了指定子类型的原型而调用超类型的构造函数,使用寄生式继承来继承超类型的原型,这样就能减少超类型构造函数的调用次数 

 

原文地址:https://www.cnblogs.com/qianduangaoshou/p/6836326.html