我真的不懂JS的面向对象

我在写vools.js的时候,发现我写的对象继承的方式有点怪。后来去查阅了一下资料,还真的是这样。

今天下午写js的时候,写到这里发现了有点不对劲:

1
2
3
4
5
var UI = function (){};
UI.prototype = VoolsEvent.prototype;

如果是玩多重继承的话,那这个岂不是有问题?

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
var A = function (){
this.constructPropertyA = 'AAA';
};
A.prototype.iAmA = 'i am A';
var B = function (){
this.constructPropertyB = 'BBB';
};
B.prototype.iAmB = 'i am B';
var C = function (){
this.constructPropertyC = 'CCC';
};
C.prototype.iAmC = 'i am C';
B.prototype = A.prototype;
C.prototype = B.prototype;
for (var key in new C) {
console.log(key);
}
// console output 'iAmA'

没错,构造函数C的实例并没有 iAmBiAmC 属性。因为B声明了prototype属性后又把prototype换成A的prototype了(C也是一样)。所以只有iAmA(大煞笔vec)

什么是原型链

JS当中实现继承的方式靠的是原型链(Prototype Chain)的机制。类似于链子一样的结构

[A (constructPropertyA), {iAmA}]
 ↓
[B (constructPropertyB), {iAmB}]
 ↓
[C (constructPropertyC), {iAmC}]

new C;
/*
C {
	constructPropertyC,
	prototypeChain: B {
		iAmB,
		prototypeChain: A {
			iAmA
		}
	}
}
*/

如果你想访问**C实例中的iAmA**属性的话,JS首先会访问最高层的属性(就是constructPropertyC那层),如果没找到iAmA的话,则到prototypeChain里继续搜索,直到最底层。

当然,JS里可不是上面那样的:

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
function Animal(){}
Animal.prototype.type = '哺乳动物';
Animal.prototype.setAge = function (value){
this.age = value;
};
function People(){}
People.prototype.setName = function (value){
this.name = value;
};
function Female(name, age){
this.setName(name);
this.setAge(age);
}
Female.prototype.sex = '女';
People.prototype.__proto__ = Animal.prototype;
Female.prototype.__proto__ = People.prototype;
var 妹子 = new Female('lily', 17);
for (var key in 妹子) {
console.info(key);
}
// console output 'name'
// console output 'age'
// console output 'sex'
// console output 'setName'
// console output 'type'
// console output 'setAge'

终于实现了应该要有的效果了。。。然后我要继续写[1]代码了


  1. 之前写错的地方。。。也得改过来orzorzorz ↩︎