佳宸学习和分享笔记的地方

0%

如何实现JS继承

如何实现JS继承

JS是通过链式继承的,ES6的继承实际是语法糖。自己手动实现一下继承加深印象。

es6之前是不支持接口直接继承的,所以就需要手动实现继承

通过这个图先熟悉一下JS内部,constructor和prototype和实例的关系

image-20200115231115613

原型链继承

1
2
// 把父的实例化对象,赋值给 child的原型对象
Child.prototype = new Parent()

问题一: 当原型链中包含引用类型值的原型时,该引用类型值会被所有实例共享;

问题二: 在创建子类型(例如创建Child的实例)时,不能向父类型(例如Parent)的构造函数中传递参数.

构造函数继承

1
2
3
4
function Child() {
// call只能继承属性,不能继承方法
Parent.call(this)
}

问题一:父类中定义的方法,对子类型而言也是不可见的

问题二:方法都在构造函数中定义, 因此函数复用也就不可用了

组合继承

使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承.

1
2
3
4
5
6
7
8
9
10
11
12
function Parent() {
this.name = 'parent'
this.play = [1,2,3]
}
function Child() {
// call只能继承属性,不能继承方法
Parent.call(this)
this.type = 'child'
}
// 把父的实例化对象,赋值给 child的原型对象
Child.prototype = new Parent()
console.log(new Child)

缺点:调用了两次父类构造函数, 造成了不必要的消耗

寄生组合式继承

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的protoMDN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Parent() {
this.name = 'parent'
this.play = [1,2,3]
}
function Child() {
// call只能继承属性,不能继承方法
Parent.call(this)
this.type = 'child'
}
// 把父的实例化对象,赋值给 child的原型对象
Child.prototype = Object.creat(Parent.prototype)
// 将子原型对象的构造函数指回来
Child.prototype.constructor = Child
console.log(new Child)

如果你希望能继承到多个对象,则可以使用混入的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function MyClass() {
SuperClass.call(this);
OtherSuperClass.call(this);
}

// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
// do a thing
};

ES6 class继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Parent {
constructor(value) {
this.val = value
}
getValue() {
console.log(this.val)
}
}
// extends 表明继承自哪个父类
class Child extends Parent {
constructor(value) {
super(value)
this.val = value
}
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent // true