JavaScript的继承

之前遇到过一道题:说什么是js的混合继承?无知的我以为是:对象自身属性和原型上方法的继承。妥妥的打脸啊[捂脸](写完这篇文章后,发现我这个说法好像也是没啥毛病啊,混合继承就是用对象冒充来继承另外一个构造函数的自身属性,改写对象prototype指向另外一个对象,就是对象自身属性和原型的继承嘛[捂脸])

那么首先来说说继承机制的实现方式吧:

首先是基类的创建,再就是子类的创建,创建的子类将继承超类的所有属性和方法,包括构造函数以及方法的实现。所有属性和方法都是公用的,因此子类可以直接访问这些方法。子类还可以添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。

javascript中继承的方式:

1.对象冒充

原理:构造函数使用 this 关键字给所有属性和方法赋值,所以可使ClassA 构造函数成为ClassB的方法,然后调用它,ClassB就会收到ClassA中定义的属性和方法。例如:

function ClassA(sColor){
    this.color = sColor;
    this.sayColor = function(){
        alert(this.color);
    }
}
function ClassB(sColor,sName){
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;
    this.sayName = function(){
        alert(sName);
    }
}

var objA = new ClassA("blue");
var objB = new ClassB("red","miya");
objA.sayColor();   //blue
objB.sayColor();   //red
objB.sayName();    //miya

ClassA赋予了方法newMethod(函数名只是指向它的指针),然后调用该方法,传递给的是ClassB的参数sColor,所有新属性和新方法都必须在删除了新方法的代码行后定义,否则可能会覆盖超类的相关属性和方法。

对象冒充可以实现多重继承

 

一个类可以继承多个超类。如果存在两个类ClassX和ClassY具有同名的属性或者方法,下面的ClassY具有更高的优先级。所以多个对象继承时候注意下属性方法的覆盖。

在javascript中call()和apply()就是对象冒充最为相似的方法。

function sayColor(f){
    console.log(`${f} ${this.color}`);
}
var obj =  new Object();
obj.color = 'green';
sayColor.call(obj,'I like')   //I like green

sayColor()里面的this关键字指向obj,对象冒充和继承机制一起使用,如下:

function ClassA(sColor){
    this.sayColor = function(){
        alert(sColor);
    }
}
function ClassB(sColor,sName){
    ClassA.call(this,sColor);
    this.name = sName;
    this.sayName = function(){
        alert(this.name);
    }
}
var c = new ClassB('green','miya');
c.sayColor() //green
c.sayName() //miya

ClassB继承了ClassA的方法。apply和call作用相同,只是传参形式不同,apply传递的是数组形式的。

2.原型链的继承

prototype是个模板,要实例化的对象都以这个模板为基础,prototype对象的任何属性和方法都被传递给那个类的所有实例。 

ClassB.prototype = new ClassA();

 将ClassB的原型指向了一个ClassA的实例对象上,所以,ClassB的 原型就是ClassA的实例对象。

var objB = new ClassB();
objB instanceof ClassA
//true
objB instanceof ClassB
//true

原型链的弊端:不支持多重继承,会重写类的prototype属性。

3,混合方式继承

终于说到话题最开始的时候了,什么是混合继承?

使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,如果使用原型链就无法使用带参数的构造函数,对象冒充和原型链继承方式都用,就是混合继承。

创建类最好的方式:用构造函数定义属性,用原型定义方法。

混合继承就是:用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。

function ClassA(scolor){
    this.color = scolor;
}
ClassA.prototype.sayColor = function(){
    console.log(this.color);
}
function ClassB(scolor,sname){
    ClassA.call(this,scolor);
    this.name = sname;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function(){
    console.log(this.name);
}
var objA = new ClassA("blue");
var objB = new ClassB("red","miya");
objA.sayColor();  //blue
objB.sayColor();  //red
objB.sayName(); //miya

objA instanceof ClassA     //true
objB instanceof ClassA     //true
objB instanceof ClassB      //true

在该例子中,继承的突出在于,ClassB构造函数中,用对象冒充继承了ClassA的自身属性,将ClassB的原型对象指向了ClassA的实例对象上面,然后再在原型上面添加新的方法。
因为使用了原型链,所以可以使用instanceof进行测试:对象是否继承某个类的原型

 

posted @ 2018-04-27 20:50  tangjiao_Miya  阅读(224)  评论(0编辑  收藏  举报