JavaScript的继承

8/6/2021 Javascript

# 原型链继承

function Parent() {
    this.name = 'april'
}
Parent.prototype.getName = function() {
    console.log(this.name)
}
function Child() {}
Child.prototype = new Parent()
let child = new Child()
console.log(child.getName())
1
2
3
4
5
6
7
8
9
10

存在的问题

  • 引用类型的属性被所有实例共享
function Parent() {
    this.names = ['april', 'bran']
    this.age = 24
}
function Child() {}
Child.prototype = new Parent()
let child1 = new Child()
child1.names.push('tony')
child1.age = 26
let child2 = new Child()
console.log(child1.names, child1.age) // ['april', 'bran', 'tony']
console.log(child2.names, child2.age) // ['april', 'bran', 'tony']
1
2
3
4
5
6
7
8
9
10
11
12
  • 在创建 Child 的实例时,不能向 Parent()传参
function Parent(name) {
    this.name = name
}
function Child() {}
Child.prototype = new Parent()
let parentObj = new Parent('test1')
let childObj = new Child('test2')
console.log(parentObj)
console.log(childObj) // childObj的name属性是undefined
1
2
3
4
5
6
7
8
9

# 构造函数继承

function Parent() {
    this.names = ['april', 'bran']
}
function Child() {
    Parent.call(this)
}
let child1 = new Child()
child1.names.push('tony')
let child2 = new Child()
console.log(child1.names) // ['april', 'bran', 'tony']
console.log(child2.names) // ['april', 'bran']
1
2
3
4
5
6
7
8
9
10
11

优点

  • 避免了引用类型的属性被所有实例共享
  • 可以在 Child 中向 Parent 传参
function Parent(name) {
    this.name = name
}
function Child(name) {
    Parent.call(this, name)
}
let child1 = new Child('april')
let child2 = new Child('bran')
console.log(child1.name) // april
console.log(child2.name) // bran
1
2
3
4
5
6
7
8
9
10

缺点 方法都在构造函数中定义,每次创建实例都会创建一遍方法

# 组合继承

原型链继承和构造函数继承相结合,融合两者的优点,是常用的继承方式。

function Parent(name) {
    this.name = name
    this.colors = ['red', 'blue', 'green']
}
Parent.prototype.getName = function() {
    console.log(this.name)
}
function Child(name, age) {
    Parent.call(this, name)
    this.age = age
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
let child1 = new Child('april', 24)
child1.colors.push('white')
console.log(child1.name) // april
console.log(child1.age) // 24
console.log(child1.colors) // ['red', 'blue', 'green', 'white']
child1.getName() // april
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

缺点 会调用两次父构造函数

# 优化后的组合继承

function Parent(name) {
    this.name = name
}
Parent.prototype.getName = function() {
    console.log(this.name)
}
function Child(name, age) {
    Parent.call(this, name)
    this.age = age
}
let F = function() {}
F.prototype = Parent.prototype
Child.prototype = new F()
let child1 = new Child('april', 24)
console.log(child1.name) // april
console.log(child1.age) // 24
child1.getName() // april
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 寄生式继承

function createObj(o) {
    let clone = Object.create(o)
    clone.sayHi = function() {
        console.log('hello')
    }
    return clone
}
let temp_obj = {
    name: 'april',
    age: 24,
}
let test = createObj(temp_obj)
console.log(test.name) // april
console.log(test.age) // 24
test.sayHi() // hello
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上次更新: 8/13/2021, 5:12:51 PM