Appearance
前言
该死的八股文,问八股文的公司都是lj。
类继承
通过原型链继承,缺点有两个,原型是复制模式,当修改一个原型链的引用类型时,会直接到原型链上修改,间接的影响其他依赖原型链的对象,第二个是没法在创建子类时自定义父类的构造器参数
js
function Human(name) {
this.name = name
}
Human.prototype = {
speak() {
console.log(this.name)
},
}
Human.prototype.constructor = Human; // 重写了原型,将构造函数补全
function Man(sex) {
this.sex = sex
}
Man.prototype = new Human();
Man.prototype.constructor = Man; // 修正constructor
const ming = new Man();
ming.speak()
ming.speak.test // undefined
const ku = new Man();
ku.speak.test = 'ku'
ming.speak.test // 影响了同级的子类构造函数继承
为了解决上面问题,衍生出了构造函数继承的方案、但是这种方案总是会将父对象拷贝一份,在大量子类时不满足共享原则,其二父类原型上的方法没有继承到
js
function Human() {
this.speak = function() {
console.log(this.name)
}
}
function Man(sex, name) {
Human.call(this, name); // 每次Human() 执行都会创建一个新的speak,可以随意修改不会影响
this.sex = sex; // 同时 也会将speak绑定到speak上
}组合式继承
为了解决上面父类原型没有继承到子类的问题,组合式继承就是构造函数继承和类继承的结合。缺点也有就是父构造函数会执行两次,对于父构造函数开销比较大比较耗时
js
function Human(name) {
this.name = name
}
Human.prototype.speak = function() {
console.log(this.name)
}
function Man(sex, name) {
Human.call(this, name)
this.sex = sex
}
Man.prototype = new Human();
Man.prototype.constructor = Man;原型式继承
这种就是创建实例,没有了类那一套继承逻辑(然而,类不也是为了创建实例),这个缺点也是如果o上面有引用的属性,继承o的所有值会共享。Object.create() 就是这玩意儿
js
function inheritObject(o) {
function F() {}
F.prototype = o;
return new F
}寄生式继承
其实就是原型式继承的函数封装,新增了扩展子对象的方法
js
function createBook(book) {
const o = new inheritObject(book); // 有new和无new有没有区别
o.jump = function() {} // 添加了子对象独有的方法
}寄生组合式继承
上面都是直接针对对象的,如果是类就该用下面这种
js
function inheritClass(subClass, superClass) {
// 拷贝父的原型
const p = inheritObject(superClass);
subClass.prototype = p;
subClass.prototype.constructor = subClass;
}
function SubType() {
SuperType.call(this)
}
inheritClass(SubType, SuperType)