class继承
继承的实现方法五花八门,随便百度一下,都有好几种实现方式,幸好Es6用实现了继承的语法糖。我们先看看Es6的继承有哪些特点
Es6的继承
function Father() {
this.name = 'father'
};
Father.prototype.age = 100;
class ClassSon extends Father {
}
let classSon = new ClassSon();
console.log('classSon name', classSon.name) //fater
console.log('classSon age', classSon.age) // 100
console.log('classSon instanceof ClassSon', classSon instanceof ClassSon) // true
console.log('classSon instanceof Father', classSon instanceof Father) //true
console.log('classSon', classSon)
接下来我们一步一步实现Es6的class
实例继承
- 实例赋值原型,这样不仅把Father的name属性给了SonA,还把原型属性也给了SonA,因为Fahter实例上包含Fathe的原型属性
function Father() {
this.name = 'father'
};
Father.prototype.age = 100;
function SonA() {
}
SonA.prototype = new Father()
let classSon = new SonA()
console.log('SonA name', classSon.name) //fater
console.log('SonA age', classSon.age) // 100
console.log('SonA instanceof SonA', classSon instanceof SonA) // true
console.log('SonA instanceof Father', classSon instanceof Father) //true
console.log('SonA', classSon)
- 看起来很美好,所有的用例都过了。但是有一个最明显的缺陷,那就是无法把子类构造函数的参数传给父类
- 在看下打印出来的子类实例,也有问题:name属性不在SonA的实例上; SonA的constructor指向父类
call借用父类的构造函数属性
function Father() {
this.name = 'father'
};
Father.prototype.age = 100;
function SonB(name) {
Father.call(this,name)
}
const classSon = new SonB()
console.log('SonB name', classSon.name) //fater
console.log('SonB age', classSon.age) // undefined
console.log('SonB instanceof SonB', classSon instanceof SonB) // true
console.log('SonB instanceof Father', classSon instanceof Father) //false
console.log('SonB', classSon)
- Father.call(this,name)。大家都知道call的作用是改变this的指向。那么这句话的意思就是把Fahter里面的实例属性都指向给了SonB。所以相当于给了SonB的实例增加了属性
- 看下打印的实例:有name属性,construct也指向正确,但是和Father没有啥关系了,所以仅仅借用Father的属性也是不行的
- 从这里看出完成了部分功能,但是原型属性没有继承,并且与Father没有联系。接下来我们看看能否增强上面的代码
原型赋予
- 上面的例子中,原型没有赋予给子类,我们可以尝试把原型直接丢给子类原型
function Father() {
this.name = 'father'
};
Father.prototype.age = 100;
function SonC(name) {
Father.call(this,name)
}
SonC.prototype = Father.prototype
- 但是这样的有个很大的缺陷,就是修改SonC的原型的同时,也会修改Father的原型。这不符合面向对象的逻辑,所以我们需要一个中介来实现这个赋予功能
寄生
- Object有个Api: Object.create,MDN的解释是创建一个对象,让他的__proto__指向另一个对象。这样一看很符合咱们的要求。
function Father() {
this.name = 'father'
};
Father.prototype.age = 100;
function SonB(name) {
Father.call(this,name)
}
// 创建一个寄生器
const pro= Object.create(Father.prototype)
/**
也有种创建方法,其实意思都一样
const Super = function(){}
Super.prototype = Father.prototype
SonB.prototype = new Super()
SonB.prototype.constructor = SonB
**/
//修复构造函数指向
pro.constructor = SonB
//原型赋予
SonB.prototype = pro
const classSon = new SonB()
console.log('SonB name', classSon.name) //fater
console.log('SonB age', classSon.age) // 100
console.log('SonB instanceof SonB', classSon instanceof SonB) // true
console.log('SonB instanceof Father', classSon instanceof Father) //true
console.log('SonB', classSon)
- 看下实例,与es6相同,实现完成