JS继承(ES5的6种继承 and ES6新增)

tech2022-07-05  163

ES5 有 6 种方式可以实现继承,分别为

1.原型链继承

父类的实例作为子类的原型

原型链继承的基本思想是:

利用原型让一个引用类型继承另一个引用类型的属性和方法。

//原型链继承 function Fu() { this.name = "张三"; this.age = 2; } Fu.prototype.child = function() { return this.name; }; let a = new Fu(); console.log(a.child());//张三

优点:

简单易于实现,父类的新增的实例与属性子类都能访问

缺点:

可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面无法实现多继承创建子类实例时,不能向父类构造函数中传参数

2、借用构造函数继承(伪造对象、经典继承)

复制父类的实例属性给子类

借用构造函数的技术,基本思想为:

在子类型的构造函数中调用超类型构造函数。

//构造函数继承 function Fu(name){ this.name = name; } function Student(name){ Fu.call(this,name); } let a = new Student("海绵宝宝"); console.log(a.name);//海绵宝宝

优点:

可以向超类型的构造函数传递参数解决了原型中包含 引用类型值被所有实例共享的问题

缺点:

方法都在构造函数中定义,无法复用不能继承原型属性/方法,只能继承父类的实例属性和方法

3.实例继承(原型式继承)

原型继承的基本思想是:

借用原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

// 原型式继承 var person = { name:"大头儿子", age:2 } var person1 = Object.create(person); person1.name = "小头爸爸"; person1.age = 26; var person2 = Object.create(person); person2.name = "围裙妈妈"; person2.age = 23; console.log(person1);// {name: "小头爸爸", age: 26} console.log(person2);// {name: "围裙妈妈", age: 23}

优点:

不限制调用方法,简单,易实现

缺点:

不能多次继承

4.组合继承(原型链 + 借用构造函数)

( 组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。)

调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用

基本思路:

使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对每个实例属性的继承,既通过了在原型上定义方法来实现了函数复用,有保证了每个实例都有自己的属性。

//组合继承(原型链和借用构造函数) function Fu(name){ this.name = name; } Fu.prototype.sayHi = function (){ console.log(this.name) } function Student(name){ Fu.call(this,name) } let a = new Student("派大星"); console.log(a.name);//派大星

5、寄生式继承

( 寄生式继承是与原型式继承紧密相关的一种思路。 )

寄生式继承的思路与寄生构造函数和工厂模式类似:

即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了搜有的工作一样返回对象。

// 寄生式继承 function createAnother(original){ var clone = Object(original); clone.sayHi = function (){ console.log("hi"); }; return clone; } var person = { name:'张三', age:2 } var person2 = createAnother(person); person2.sayHi();//hi

缺点:

使用寄生继承来为对象添加函数,会由于不能做到函数复用而效率低下。同原型链实现继承一样,包含引用类型值的属性会被所有实例共享

6.寄生组合继承

通过寄生的方式来修复组合是继承的不足,完美的实现继承

所谓寄生组合式继承,即通过构造函数来继承属性,通过原型链的混成形式来继承方法。

基本思路:

不必为了指定子类型的原理而调用超类型的构造函数,我们需要的仅仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后,再将结果指定给子类型的原型。

// 寄生组合式继承(构造函数和原型的结合)最理想的继承方案 function inheritPrototype(subType,superType){ var prototype = Object(superType.prototype);//创建对象 prototype.constructor = subType;//增强对象 subType.prototype = prototype;//指定对象 } function SuperType(name){ this.name = name; } SuperType.prototype.sayHi = function (){ console.log(this.name); } function SuberType(name){ SuperType.call(this,name); } inheritPrototype(SuberType,SuperType); var a = new SuperType("张三"); a.sayHi();//张三

优点:

只调用了一次超类构造函数,效率更高

ES6还新增一种继承方式

//class 相当于es5中构造函数 //class中定义方法时,前后不能加function,全部定义在class的protopyte属性中 //class中定义的所有方法是不可枚举的 //class中只能定义方法,不能定义对象,变量等 //class和方法内默认都是严格模式 //es5中constructor为隐式属性 class People{ constructor(name='wang',age='27'){ this.name = name; this.age = age; } eat(){ console.log(`${this.name} ${this.age} eat food`) } } //继承父类 class Woman extends People{ constructor(name = 'ren',age = '27'){ //继承父类属性 super(name, age); } eat(){ //继承父类方法 super.eat() } } let wonmanObj=new Woman('xiaoxiami'); wonmanObj.eat();

优点:

代码量少,易懂

ES5继承和ES6继承的区别:

es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中 Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this) es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this

最新回复(0)