继承的几种方式:
原型链继承
// 原型链继承 通过prototype function superType(){ this.color = ["red","green","blue"] } function subType(){} // 继承superType subType.prototype = new superType() let instance = new subType() instance.color.push("yellow") console.log(instance.color) // red green blue yellow
组合继承(也叫伪经典继承):结合了原型链和盗用构造函数,将两者的优点集合起来。基本思路就是使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让实例都有自己的属性。
//组合继承 function superType(name){ this.name = name this.color = ['red','yellow','blue'] } subType.prototype.sayName = function(){ // 在原型上添加了一个sayName方法 console.log(this.name) } function subType(name,age){ superType.call(this,name) // 继承superType上的属性 this.age = age } // 继承方法 subType.prototype = new superType() subType.prototype.sayAge = function(){ console.log(this.age) } let instance = new subType("jack","20") instance.color.push("green") console.log(instance.color) // red yellow blue green console.log(instance.sayName) // jack console.log(instance.sayAge) //20
原型式继承:创建一个临时构造函数,将传入的对象赋值给这个构造函数的原型,然后返回这个临时类型的一个实例。
使用情况:你有一个对象,想在这个对象的基础上创建一个新的对象,就需要把这个对象先传给Object(),然后再对返回的对象进行适当的修改
// Object()函数创建一个临时构造函数 function obiect(o){ function F(){ F.prototype = o return new F() } } let person = { name:'jack' friend:['sam','lucy','lili'] } let anotherPerdson = object(person) // 先把一个对象传给object() anotherPerson.name = 'greg' anotherPerson.friend.push('shasha') console.log(person.friend) // 'sam lucy lili shasha'
ECMAScript5增加了Object.create()方法 这个方法接收两个参数:一个参数的时候和object()用法一样,当增加第二个参数的时候(可选),可以给对象定义额外的属性
// Object.create() function object(o){ function F(){ F.prototype = o return new F() } } let person = { name:'jack' friend:['ss','zz','bb'] } let anotherPerson = Object.create(perwson,{ name:{ value:'greg' } }) console.log(anotherPerson.name) // greg
寄生式继承:
寄生式组合继承(引用类型继承的最佳模式):
function inserit(son,father){ var obj = Object.create(father.prototype) // 创建对象(创建父类原型的一个副本) obj.constructor = son // 增强对象(解决由于重写原型导致默认constructor丢失的问题) son.prototype = obj; // 赋值对象(将新创建的对象赋值给子类原型) } function SuperType(name,colors){// 定义一个父类 this.name = name; this.colors = colors } SuperType.prototype.sayName = function(){// 在supertype原型上添加了一个sayName方法 return this.name } function SubType(job,name,color){//定义一个子类 SuperType.call(this,name,color) // 继承了父级supertype的属性 this.job = job // 添加了新的属性 } inserit(SubType,SuperType) // 函数实现寄生式组合继承的核心逻辑,接收两个参数,子类构造函数和父类构造函数 SubType.prototype.sayJob = function(){// 在子类上添加syaJob方法 return this.job } var instance = new SubType("doctor","john",["red","green"]) console.log(instance.sayJob(),instance.sayName())
ES5和ES6继承的区别:
1.ES5 的继承实质是先创建子类的实例对象,然后再将父类的方法添加 到 this 上(Parent.call(this)).
2.ES6 的继承机制完全不同,实质上是先创建父类的实例对象 this(所以必 须先调用父类的super()方法),然后再用子类的构造函数修改 this。
3.ES5 的继承时通过原型或构造函数机制来实现。
4.ES6 通过 class 关键字定义类,里面有构造方法,类之间通过 extends 关 键字实现继承。
//ES6继承写法 通过extends关键词 class father{ constructor(name,age){ this.name = name this.age = age } } class son extends father{ constructor(name,age,job){ super(name,age) this.job = job } } var instance = new son('jack','18','doctor') console.log(instance)
5.子类必须在 constructor 方法中调用 super 方法,否则新建实例报错。因 为子类没有自己的 this对象,而是继承了父类的 this 对象,然后对其进行加工。 如果不调用 super 方法,子类得不到 this 对象。
6.注意 super 关键字指代父类的实例,即父类的 this 对象。 注意:在子类构造函数中,调用 super 后,才可使用 this关键字,否则报错
如果你觉得文章对您有用,麻烦点个赞哦👍