继承的本质: 子类继承父类的属性和方法。(目的是让子类的实例可以调取父类的属性和方法。)
ES5中的继承
- 原型继承
-
原理: 让父类中的属性和方法在子类实例的原型链上
CHILD.prototype = new PARENT()
CHILD.prototype.constrctor = CHILD
-
特点:
- 不像其他语言一样的继承(其他语言的继承是拷贝继承,会把父类的属性和方法拷贝到子类中,供子类调取使用),它是把父类的实例放在子类实例的原型链上,实例想调取这些方法,是基于__proro__原型链查找机制完成的。
- 子类可以重写父类上的方法,会导致父类其他的实例也会收到影响。
- 父类中私有或者公有的属性方法,最后都会变成子类中公有方法。
-
// 原型链继承举🌰
// 父类
function Parent(x) {
this.x = x
}
Parent.prototye.getX = function() {
console.log(this.x)
}
// 子类
function Child(y) {
this.y = y
}
// 继承
Child.prototype = new Parent('y') // 子类的原型指向父类的实例
Child.prototype.constrctor = Child // 保证子类构造函数的完整性
Child.prototype.getY = function() {
console.log(this.y)
}
const child = new Child('x')
child.y // y 成功访问子类属性
child.x // x 成功访问父类属性
child.getX() // x 成功调用父类方法
child.getY() // y 成功调用子类本身方法
// 子类可以通过 CHILD.prototype.__proto__修改父类,并对父类的其他实例造成影响
Child.prototype.__proto__.other = function () {
console.log('other')
}
const parent = new Parent(200)
parent.other() // other
- CALL继承
- 原理:
- 在CHILD方法中把PARENT方法当作普通函数来执行,让PARENT中的this指向CHILD的实例,相当于给CHILD实例是设置了很多私有的属性和方法
- 特点:
- 只能继承父类私有的属性和方法(因为是把PARENT当作普通函数执行,和其原型上的属性和方法没有关系)
- 父类私有变为子类私有
- 原理:
// CALL继承举🌰
// 父类
function Parent(x) {
this.x = x
this.thisGetX = function () {
console.log(this.x)
}
}
Parent.prototype.getX = function () {
console.log(this.x)
}
// 子类
function Child(y) {
// this => Child的实例
Parent.call(this, 200)
this.y = y
}
Child.prototype.getY = function () {
console.log(this.y)
}
const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() // 报错 无法访问父类原型链上的属性和方法
- 寄生组合继承
- 原理: CALL继承+类似原型继承
- 特点:
- 父类私有和公有的属性、方法,分别是子类实例的共同和私有方法(推荐)
// 寄生组合继承举🌰
// 父类
function Parent(x) {
this.x = x
this.thisGetX = function () {
console.log(this.x)
}
}
Parent.prototype.getX = function () {
console.log(this.x)
}
// 子类
function Child(y) {
// this => Child的实例
Parent.call(this, 200)
this.y = y
}
// Object.create => 创建一个空对象,让空对象__proto__指向 Parent.prototype
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() // 200
// 实现object.create方法
function create(obj) {
function Fn()
Fn.prototype = obj
return new Fn()
}
ES6中的继承
- class
- 原理: class CHILD extends Parent {} => CHILD.prototype._ proto_ = PARENT.prototype
- 特点:
- 子类继承父类可以不屑constructor,一旦写了,constructor内的第一句话必须是super(), super() 的作用类似call继承。
// 父类
// ES6中基于class创造出来的类不能当作普通函数执行、不允许重定向原型的指向
class Parent {
constructor(x) {
this.x = x
}
getX() {
console.log(this.x)
}
}
// 子类
// class Child {
// constructor(y) {
// this.y = y
// }
// getY() {
// console.log(this.y)
// }
// }
// ES6中的继承
class Child extends Parent {
constructor(y) {
super(200)
this.y = y
}
getY() {
console.log(this.y)
}
}
const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() // 成功调用父类方法