-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextend.js
More file actions
130 lines (115 loc) · 3.45 KB
/
extend.js
File metadata and controls
130 lines (115 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* 原型链继承
* 缺点1:原型中包含的引用类型属性将被所有实例共享;
* 缺点2:子类在实例化的时候不能给父类构造函数传参;
*/
function byPrototype() {
function Parent() {
this.colors = ['black']
}
function Child(name) {
this.name = name
}
// constructor 属性表示原型对象与构造函数之间的关联关系,修改原型时记得同时修改
Child.prototype = new Parent()
Child.prototype.constructor = Child
let child1 = new Child('xx')
console.log(child1)
console.log(child1.name) // xx
console.log(Object.keys(child1)) // [ 'name' ]
child1.colors.push('white')
let child2 = new Child('yy')
console.log(child2.colors) // ['black', 'white']
}
byPrototype()
/**
* 构造函数继承
* 1. 避免了引用类型的属性被所有实例共享;
* 2. 可以向 Parent 传参
* 缺点:父类方法只能在构造函数中定义,每次创建实例都会创建一遍方法
*/
function byConstructor() {
function Parent(name) {
this.name = name
this.colors = ['black']
this.go = function () {
console.log('go!', this.name)
}
}
function Child(name) {
Parent.call(this, name)
}
let child1 = new Child('xx')
console.log(child1)
child1.colors.push('white')
console.log(child1.name) // xx
let child2 = new Child('yy')
console.log(child2.name) // yy
console.log(child2.colors) // ['black']
}
// byConstructor()
/**
* 组合继承
* 融合了原型链继承和构造函数继承的优点
* 缺点:父构造函数被调用了两次
*/
function compose() {
function Parent(name) {
console.log('[Parent] constructor') // 打印了两次
this.name = name
this.colors = ['black']
}
Parent.prototype.go = function () {
console.log('go!', 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('tom', 18)
child1.colors.push('white')
console.log(child1.colors)
child1.go()
let child2 = new Child('jack', 20)
console.log(child2.colors)
console.log(child2.age)
}
// compose()
/**
* 寄生组合式继承
*/
function parasiticCompostion() {
function Parent(name) {
console.log('[Parent] constructor')
this.name = name
this.colors = ['black']
}
Parent.prototype.go = function () {
console.log('go!', this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
// 关键一步:构造新对象指向父类原型
// 这一步不会调用父类的构造方法,从而解决了组合式继承的缺点
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
let child = new Child('justorez', 18)
child.go()
console.log(child)
console.log(child instanceof Child)
}
// parasiticCompostion()
// 将寄生组合式继承封装一下
function objectCreate(o) {
function F() {}
F.prototype = o
return new F()
}
function prototype(Child, Parent) {
Child.prototype = Object.create(Parent.prototype) // 和 objectCreate() 功能相同
Child.prototype.constructor = Child
}