ES5 继承方式
1、原型链继承
function A(name) { this.name = name } A.prototype.getName = function() { return this.name } function B() { this.bName = "L" } B.prototype = new A("H"); let b = new B();
优点:实现比较简单,能通过instanceOf和isPrototypeOf的检测。
缺点:1. 在通过原型链实现继承时,原型实际上会成为另一个类型的实例, 父类的实例属性实际上会成为子类的原型属性。结果就是所有的子类的实例都会共享父类的实例属性(引用类型的)。
2. 在创建子类型的实例时,没有办法在不影响所有实例的情况下,向父类型的构造函数传递参数。因此实践中很少单独使用原型链继承。
2、构造函数继承
function A(name) { this.name = name } function B(nameParam) { A.call(this, nameParam) } let b = new B("H");
优点:可以向父类构造函数传参数,并且每一个子类实例都有父类属性和方法的副本
缺点:正是因为这种方法调用父类,所以也只能继承父类的属性和方法,且继承的方法也无法复用。并且不能继承父类原型的属性和方法。(子类原型并未链接父类原型)
3、组合继承
function A(name) { this.name = name } A.prototype.getName = function() { return this.name; } function B(nameParam, ageParam) { A.call(this, nameParam); this.age = ageParam; } B.prototype = new A("H"); let b = new B("L", 23);
优点:组合继承避免了原型链和借用构造函数的缺陷。融合了他们的优点成为JavaScript中最常用的继承模式。而且instanceof 和 isPrototypeOf() 也能够用于识别基于组合继承创建的对象。
缺点:组合继承调用了两次父类,因此子类实例和子类的原型上各存有一份父类实例的属性和方法。
4、原型式继承
function A(obj) { function fn() {} fn.prototype = obj return new fn() } let b = { name: "H", play: function() { console.log(`${this.name} is playing`); } } let c = new A(b);
优点:在没有必要兴师动众的创建构造函数,而只想让一个对象与另外一个对象保持类似的情况下,原型式继承是完全可以胜任的。
缺点:包含引用类型值的属性始终都会共享相同的值,并且这种方法有局限性。
5、寄生继承
function A(obj) { function fn() {}; fn.prototype = obj; return new fn(); } function generate(people) { let b = A(people); b.getName = function() { console.log(`His name is ${this.name}`) } return b; } let p = { name: "H", play: function() { console.log(`${this.name} is playing`) } } let b = generate(p);
优点:在主要考虑对象,而不是自定义类型和构造函数的情况下,寄生式继承也是一种可选方案。
缺点:和原型继承类似有一定局限性。
6、寄生组合式继承
function A(name) { this.name = name } A.prototype.getName = function() { console.log(`His name is ${this.name}`) } function B(nParam, aParam) { A.call(this, nParam); this.age = aParam; } function generate(Parent, Child) { let proto = Object.create(Parent.prototype); proto.constructor = Child; Child.prototype = proto; } generate(B,A); let c = new B()
new:
{ var obj = {}; var res = func.call(obj); return typeof res ==="Object"? res: obj; }
Object.create:
{ function fn() {}; fn.prototype = obj; return new fn(); }