Skip to content

Commit 86311e3

Browse files
committed
JavaScript深入之继承
1 parent de290b3 commit 86311e3

File tree

1 file changed

+253
-0
lines changed

1 file changed

+253
-0
lines changed

JavaScript深入之继承.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# JavaScript深入之继承
2+
3+
跟《JavaScript深入之创建对象》一样,更像是笔记,哎,再让我感叹一句:《JavaScript高级程序设计》写得真是太好了!
4+
5+
1.原型链继承
6+
7+
```js
8+
function Parent () {
9+
this.name = 'kevin';
10+
}
11+
12+
Parent.prototype.getName = function () {
13+
console.log(this.name);
14+
}
15+
16+
function Child () {
17+
18+
}
19+
20+
Child.prototype = new Parent();
21+
22+
var child1 = new Child();
23+
24+
console.log(child1.getName()) // kevin
25+
```
26+
27+
问题:
28+
1.引用类型的属性被所有实例共享
29+
30+
```js
31+
function Parent () {
32+
this.names = ['kevin', 'daisy'];
33+
}
34+
35+
function Child () {
36+
37+
}
38+
39+
Child.prototype = new Parent();
40+
41+
var child1 = new Child();
42+
43+
child1.names.push('yayu');
44+
45+
console.log(child1.names); // ["kevin", "daisy", "yayu"]
46+
47+
var child2 = new Child();
48+
49+
console.log(child2.names); // ["kevin", "daisy", "yayu"]
50+
51+
```
52+
53+
2.在创建Child的实例时,不能向Parent传参
54+
55+
2.借用构造函数(经典继承)
56+
57+
```js
58+
function Parent () {
59+
this.names = ['kevin', 'daisy'];
60+
}
61+
62+
function Child () {
63+
Parent.call(this);
64+
}
65+
66+
var child1 = new Child();
67+
68+
child1.names.push('yayu');
69+
70+
console.log(child1.names); // ["kevin", "daisy", "yayu"]
71+
72+
var child2 = new Child();
73+
74+
console.log(child2.names); // ["kevin", "daisy"]
75+
```
76+
77+
优点:
78+
1.避免了引用类型的属性被所有实例共享
79+
2.可以在Child中向Parent传参
80+
81+
举个例子:
82+
83+
```js
84+
function Parent (name) {
85+
this.name = name;
86+
}
87+
88+
function Child (name) {
89+
Parent.call(this, name);
90+
}
91+
92+
var child1 = new Child('kevin');
93+
94+
console.log(child1.name); // kevin
95+
96+
var child2 = new Child('daisy');
97+
98+
console.log(child2.name); // daisy
99+
100+
```
101+
102+
缺点:
103+
104+
1. 方法都在构造函数中定义,每次创建实例都会创建一遍方法。
105+
106+
3.组合继承
107+
108+
```js
109+
function Parent (name) {
110+
this.name = name;
111+
this.colors = ['red', 'blue', 'green'];
112+
}
113+
114+
Parent.prototype.getName = function () {
115+
console.log(this.name)
116+
}
117+
118+
function Child (name, age) {
119+
120+
Parent.call(this, name);
121+
122+
this.age = age;
123+
124+
}
125+
126+
Child.prototype = new Parent();
127+
128+
var child1 = new Child('kevin', '18');
129+
130+
child1.colors.push('black');
131+
132+
console.log(child1.name); // kevin
133+
console.log(child1.age); // 18
134+
console.log(child1.colors); // ["red", "blue", "green", "black"]
135+
136+
var child2 = new Child('daisy', '20');
137+
138+
console.log(child2.name); // daisy
139+
console.log(child2.age); // 20
140+
console.log(child2.colors); // ["red", "blue", "green"]
141+
142+
```
143+
144+
优点:融合原型链继承和构造函数的优点,是JavaScript中最常用的继承模式。
145+
146+
4.原型式继承
147+
148+
```js
149+
function object(o) {
150+
function F(){}
151+
F.prototype = o;
152+
return new F();
153+
}
154+
```
155+
156+
就是ES5 Object.create的模拟实现,将传入的对象作为创建的对象的原型。
157+
158+
5. 寄生式继承
159+
160+
创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。
161+
162+
```js
163+
function createObj (o) {
164+
var clone = object.create(o);
165+
clone.sayName = function () {
166+
console.log('hi');
167+
}
168+
return clone;
169+
}
170+
```
171+
172+
6. 寄生组合式继承
173+
174+
组合继承最大的缺点是会调用两次父构造函数
175+
176+
一次在创建子类型原型的时候:
177+
178+
```js
179+
Child.prototype = new Parent();
180+
```
181+
182+
一次在创建子类型实例的时候:
183+
184+
```js
185+
var child1 = new Child('kevin', '18');
186+
```
187+
188+
所以我们不使用 Child.prototype = new Parent() 的方式,而是间接的让Child.prototype能委托访问到Parent.prototype
189+
190+
看看如何实现:
191+
192+
```js
193+
function Parent (name) {
194+
this.name = name;
195+
this.colors = ['red', 'blue', 'green'];
196+
}
197+
198+
Parent.prototype.getName = function () {
199+
console.log(this.name)
200+
}
201+
202+
function Child (name, age) {
203+
204+
Parent.call(this, name);
205+
206+
this.age = age;
207+
208+
}
209+
210+
// 关键的三步 start
211+
var F = function () {};
212+
213+
F.prototype = Parent.prototype;
214+
215+
Child.prototype = new F();
216+
// end
217+
218+
var child1 = new Child('kevin', '18');
219+
220+
```
221+
222+
最后我们封装一下这个继承方法
223+
224+
```js
225+
226+
function object(o) {
227+
function F() {}
228+
F.prototype = o;
229+
return new F();
230+
}
231+
232+
function inheritPrototype(subType, superType) {
233+
var prototype = object(superType.prototype);
234+
prototype.constructor = subType;
235+
subType.prototype = prototype;
236+
}
237+
238+
// 当我们使用的时候:
239+
inheritPrototype(Child, Parent);
240+
241+
```
242+
243+
244+
245+
246+
247+
248+
249+
250+
251+
252+
253+

0 commit comments

Comments
 (0)