构造函数
首先来一个父类的构造函数
// 父类
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.personLogAge = function(){
console.log(this.age);
}
let person1 = new Person('xiao', 20, 'male');
console.log(person1);
原型链继承
将父类的实例作为子类的原型
// 父类
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
Person.prototype.personLogAge = function(){
console.log(this.age);
}
// 子类
function Personal(other) {
this.other = other
}
Personal.prototype = new Person('yuan', 17, 'female') // 继承
let personal1 = new Personal('job');
console.log(personal1);
缺点:
- 要想为子类新增原型属性和方法,则必须在
new Person()
之后执行 - 来自原型对象的所有属性被所有实例共享
- 创建子类实例时,无法向父类构造函数传参
- 不能实现多继承
借用构造函数继承
在子类的构造函数的内部调用父类构造函数,等于是复制父类的实例属性给子类
// 父类
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
Person.prototype.personLogAge = function(){
console.log(this.age)
}
// 子类
function Personal(name, age, gender, other) {
Person.call(this, name, age, gender) // 继承
this.other = other
}
let personal1 = new Personal('yuan', 17, 'female', 'job')
console.log(personal1)
缺点:
- 只能继承父类的实例属性和方法,不能继承原型属性和方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
组合继承(最常用)
结合原型链接触和构造函数继承
// 父类
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
Person.prototype.personLogAge = function(){
console.log(this.age)
}
// 子类
function Personal(name, age, gender, other) {
Person.call(this, name, age, gender) // 继承实例属性和方法
this.other = other
}
Personal.prototype = new Person() // 继承原型属性和方法
Personal.prototype.constructor = Personal
let personal1 = new Personal('yuan', 17, 'female', 'job')
console.log(personal1)
缺点:
- 调用了两次父类构造函数,生成了两份实例(只是子类实例将原型上的实例屏蔽了而已)
react中看继承
相信学习react
的时候都会看到下面这段代码
import React, { Component } from 'react'
class Login extends Component {
constructor () {
super()
}
render () {
return (
<div>Login</div>
)
}
}
export default Login
这里看到constructor
和super
关键字,如果这里不用super
会报错,从这里切入,我们聊聊es5和es6实现继承的区别。
es5和es6继承区别
es5继承:
function parent(a, b) {
this.a = a
this.b = b
}
function child(c) {
this.c = c
}
parent.call(child.prototype, 1, 2)
使用call
实现继承的底层原理其实是
child.prototype = new parent(1, 2)
由此可见,es5整体继承的过程是
- 创建子类
child
实例对象 - 将父类
parent
的属性赋值给子类对象原型,实现继承
es6继承
class parent {
constructor(a, b) {
this.a = a
this.b = b
}
}
class child extends parent {
constructor(a, b, c) {
super(a, b)
this.c = c
}
}
由此可见,es6整体继承的过程是
- 先创建父类
- 在实例子类中通过调用
super
拿到父类的this
- 再修改
this
的值(加上子类的属性和方法)实现继承
总结
总体来说,es5和es6继承最大的区别就是
1、es5先创建子类,再实例父类并添加到子类this中
2、es6是先创建父类,再实例子类中通过关键字super
访问父类,通过修改this
实现继承