构造函数的继承方式

主要分为两部分,第一部分是ES5环境下的继承,另外一部分是ES6部分的继承,首先先看ES5,如何通过构造函数的形式实现继承。

1:原型链继承
function Foo(name) {
    this.name = name;
}
Foo.prototype.age = function() {
    console.log('父类:' + this.name);
};
function fn (name) {
    this.name = name;
}
fn.prototype = new fn();
fn.prototype.age = function() {
    console.log('子类:' + this.name);
};
var a = new fn('lisi');
a.age();

这种方法缺点比较明显,看起来很不直观,而且子类的方法不能优先于父类方法出现,通过new调用时,不能直接调用父类的构造函数而是要调用子类。


2:类式继承
function Foo(name) {
    this.name = name;
}
Foo.prototype.age = function() {
    console.log('父类:' + this.name);
};
Foo.prototype.obj = function() {
    console.log('hello world');
};
function fn (name) {
    Foo.call(this,name);
}
fn.prototype.age = function() {
    console.log('子类:' + this.name);
};
var a = new fn('lisi');
a.age();
a.obj();    //TypeError: a.obj is not a function
这里通过call的方法,将this绑定在Foo构造函数上运行,但是会导致没有自己的原型对象,无法共享原型的方法和属性。

3:组合式继承
function Foo(name) {
    this.name = name;
}
Foo.prototype.age = function() {
    console.log('父类:' + this.name);
};
Foo.prototype.obj = function() {
    console.log('hello world');
};
function fn (name) {
    Foo.call(this,name);    //第二次调用
}
fn.prototype = new Foo();   //第一次调用
fn.prototype.constructor = fn;
fn.prototype.age = function() {
    console.log('子类:' + this.name);
};
fn.prototype.set = function() {
    console.log('set si es5');
};
var a = new fn('lisi');
a.age();
a.obj();
a.set();

这是比较常用的继承方法,通过调用两次实现了继承,具备了原型链继承和类式继承的优点也可以自己定制方法或者属性。
不过缺点就是第一次调用Foo函数,实际上我们只是想获取原型,你可能在想如果通过
fn.prototype = Foo.prototype;
的方法实现,不过很可惜,这种方法是错误的,因为这会导致,两个函数的prototype属性发生改变,这显然是没有必要的。
这也是第四种继承的由来。
4:寄生组合式继承
function Foo(name) {
    this.name = name;
}
Foo.prototype.age = function() {
    console.log('父类:' + this.name);
};
Foo.prototype.obj = function() {
    console.log('hello world');
};
function fn (name) {
    Foo.call(this,name);  
}
fn.prototype = Object.create(Foo.prototype);
fn.prototype.constructor = fn;
fn.prototype.age = function() {
    console.log('子类:' + this.name);
};
fn.prototype.set = function() {
    console.log('set si es5');
};
var a = new fn('lisi');
a.age();
a.obj();
a.set();
这里使用了Object.create()方法,事实上你也可以通过这种方法自己模拟一个,使用这种方法继承,可以让Foo这个函数只执行一次。
function Create(arr) {
    function foo() {}
    foo.prototype = arr;
    return new foo();
}
 
 
5:多重继承(混合继承)
    function foo(name) {
        this.name = name;
    }

    function fn(arr) {
        this.age = arr;
    }

    function obj(name, age) {
        foo.call(this, name);
        fn.call(this, age);
    }
    obj.prototype = Object.create(foo.prototype);
    Object.assign(obj.prototype, fn.prototype);
    obj.prototype.constructor = obj;
    var a = new obj('zhangsan', 18);
    console.log(a); //obj {name: "zhangsan", age: 18}


class继承

class是ES6新增的,继承通过extends实现
class Foo {
    constructor(name) {
        this.name = name;
    }
    age() {
        console.log(this.name);
    }
    obj() {
        console.log('hello world');
    }
}
class fn extends Foo {
    constructor(name) {
        super(name);
    }
    age() {
        console.log(`子类调用${this.name}`);
    }
}
var a = new fn('zhangsan');
a.age();
a.obj();
 
 
参考文章:
30分钟学会js继承

猜你喜欢

转载自www.cnblogs.com/boses/p/9588088.html