JS的继承

对于继承的实际运用还没有很好的理解,这里就先说说JS中继承的实现。

类式继承

作为基于原型的语言,JS也可以模仿类式继承。首先声明一个父类

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayHello = function() {
    console.log("hello");
};

继承就显得复杂一点

function Programmer(name, age, work) {
    Person.apply(this, arguments);    //修正父类构造函数的this
    this.work = work;
}
Programmer.prototype = new Person();
Programmer.prototype.constructor = Programmer;
Programmer.prototype.program = function() {
    console.log("coding");
};

var p = new Programmer("jay", 26, "javascript");
p.sayHello(); //hello
console.log(p.name); //jay 注意这个不是继承属性,而是p本身的属性哦

把Programmer.prototype指向父类Person的一个实例对象,那么在子类Programmer的实例中访问成员时,如果找不到,就会去这个Person实例对象里找,还没有就到Person.prototype里找,相当于人为的设置了一条原型链来达到继承的效果。

只要不把Programmer.prototype重写,Programmer的所有实例的原型对象共享同一个对象,即Person实例。我们仍然可以通过修改原型来达到修改所有实例的效果。

有时父类的构造函数很庞大,里面有很多复杂的或我们不需要的操作,我们想要避免创建父类的实例,改进的方法是借用一个空的构造函数作为中间量来链接原型链,我们把整个过程包装到一个函数里

function inherit(subClass, superClass) {
    var F = function() {};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
subClass.superproto = superClass.prototype; //增加一个自定义属性superproto,这样我们可以通过这个属性引用到父类构造函数 }
function Programmer(name, age, work) {
    Programmer.superproto.constructor.apply(this, arguments);    //等价于Person.apply(this, arguments),这样就避免了在子类的声明中固化父类构造函数名称
    this.work = work;
}
inherit(Programmer, Person);
Programmer.prototype.program = function() {
    console.log("coding");
};

注意到,作为一个中间量,我们可以只创建一个F然后重用它,因此inherit可以这样改进一下

var inherit = (function() {
    var F = function() {};
    return function(subClass, superClass) {
        F.prototype = superClass.prototype;
        subClass.prototype = new F();
        subClass.prototype.constructor = subClass;
        subClass.superproto = superClass.prototype;
    };
})();

掺元类(Mixin)

这是一种代码重用的方法而不是严格的继承。其做法大体是,先创建一个包含各种公用方法的类,即掺元类,然后用它去扩充其它类。掺元类一般不会实例化也不直接调用,其目的就是扩充其它类,提供自己的方法。

function augment(destClass, srcClass) {
    for (method in srcClass.prototype) {
        if (!destClass.prototype[method]) {
            destClass.prototype[method] = srcClass.prototype[method];
        }
    }
}

扩充多个掺元类,变相的多继承

function augment(destClass /*, a number of srcClasses */) {
    var classes = Array.prototype.splice.call(arguments, 1);
    for (var i = 0, len = classes.length; i < len; i++) {
        var srcClass = classes[i];
        for (method in srcClass.prototype) {
            if (!destClass.prototype[method]) {
                destClass.prototype[method] = srcClass.prototype[method];
            }
        }
    }
}

参考:http://blog.csdn.net/pigpigpig4587/article/details/25152031

http://www.cnblogs.com/snandy/archive/2013/05/24/3086663.html

原文地址:https://www.cnblogs.com/coiorz/p/4740269.html