前言:
JS里边的继承是工作中必用的,也是面试中必考的,所以这篇文章就给大家介绍一下每种继承的特点,希望对大家有所收获~!
原型链继承
//父类 function Person(name) { this.name = name || 'hpp'; this.sayName = function() { return this.name; } } //子类 function Son() { this.age = 22; } Son.prototype = new Person(); var p = new Son(); console.log(p.name + p.age + p.sayName()) // hpp 22 hpp var p1 = new Per(); //修改父类对象的属性 p1.__proto__.name= 'wjf'; console.log(p.name + p1.name); // wjf wjf
关键点:让 Son构造函数的 prototype 属性 指向 一个 Person构造函数的实例!
特点:
继承实例构造函数的属性和方法
继承父类构造函数的属性和方法
缺点:
实例无法向父类构造函数传参数
单一继承,只能有一个父类
所有实例对象都共享父类的属性和方法,会导致一个实例修改父类属性,其余实例的父类属性都被修改!
借用构造函数继承:
function Person(name) { this.name = name || 'hpp'; this.sayName = function() { return this.name; } } function Man(){ this.sex = '男'; this.saySex = function(){ return this.sex; } } function Per() { Person.apply(this,['wjf']) Man.call(this) this.age = 22; } var p = new Per(); console.dir(p)
关键点:使用 call 和 apply 方法将父类的构造函数引入子类里边
特点:
继承父类构造函数的属性和方法
实例可以向父类构造函数传递参数
可以继承多个父类
缺点:
只能继承父类构造函数的属性
无法实现构造函数的复用
每个实例都有父类构造函数的副本
组合继承(原型链继承 + 构造函数继承)
function Person(name) { this.name = name || 'hpp'; this.sex = sex || 'man' } Person.prototype.sayInfo = function() { return this.name + this.sex; } function Per() { Person.apply(this, ['wjf', 'man']) this.age = 22; } Per.prototype = new Person(); Per.prototype.constructor = Per; var p = new Per(); p.sayInfo() console.dir(p)
关键点;
子类继承父类的属性
父类的公共方法放到 prototype 上边,实现多个 实例共享
缺点:
调用了两次父类
优点:
每个实例都有自己的属性,同时可以共享公共的方法
原型式继承:
function Person(name) { this.name = name || 'hpp'; this.colors = []; } function Per(obj) { function F(){}; F.prototype = obj; return new F(); } var p = new Person(); var pp = Per(p);
关键点:
用一个函数包装一个对象,然后返回这个函数的调用,object.create()就是这个原理,浅复制对象
特点:
包装对象
缺点:
原型的引用类型属性会在各实例之间共享
寄生式继承
function Person(name) { this.name = name || 'hpp'; this.colors = []; } function Object(obj) { function F(){}; F.prototype = obj; return new F(); } function CreateAnother(original){ var clone = Object(original); clone.sayHi = function(){ console.log('hi'); } return clone; } var p = new Person(); var pp = CreateAnother(p); pp.sayHi();
关键点:
创建一个用于封装继承过程的函数,这个函数可以在内部以某种方式增强对象,然后返回包装好的对象
缺点:
使用寄生方式为对象添加函数,无法做到复用
寄生组合式继承
function Person(name) { this.name = name || 'hpp'; this.colors = []; } function Object(obj) { function F(){}; F.prototype = obj; return new F(); } function CreateAnother(son,father){//寄生的关键,封装一个函数过程,用于增强对象 var clone = Object(father); clone.constructor = son; son.prototype = clone; } function Boy(name,age){ Person.call(this,name)//借用构造函数 this.age=age; } Boy.prototype.sayMyInfo = function(){ console.log(this.name,this.age); } var p = new Person(); var pp = new Boy('wjf',22); CreateAnother(pp,p); pp.sayMyInfo();
特点:
只调用了一次父类构造函数,避免了在子类的prototype上边创建爱你不必要的属性。
保持了原型链不变
正常使用 instanceof 和 isProtytypeOf() 方法
作者:靖凡无所畏惧
链接:https://blog.csdn.net/wjf1997/article/details/108555441
来源:CSDN
著作权归作者所有,转载请联系作者获得授权,切勿私自转载。