uncategorized

对javascript的一个面向对象实现的理解

今天看到一篇博客,里面是写对javascript的es5标准的一个继承方式的一个实现,先上使用的列子, 在代码里面
加入理解

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
// 继承的实现
var Class = (function () {
var _mix = function (r, s) {
for (var key in s) {
if (s.hasOwnProperty(key)) {
r[key] = s[key];
}
}
};

var _extend = function () {
// 一直对这里有个设为true, 和下面的设为false没发理解,认为是多次一举
this.initPrototype = true;
var prototype = new this();
this.initPrototype = false;

var items = Array.prototype.slice.call(arguments);
var item;

while ((item = items.shift())) {
_mix(prototype, item.prototype || item);
}

function SubClass() {
if (!SubClass.initPrototype && this.init) {
this.init.apply(this, arguments);
}
}

SubClass.prototype = prototype;

SubClass.prototype.constructor = SubClass;

SubClass.extend = _extend;

return SubClass;
};

var Class = function () {

};

Class.extend = _extend;

return Class;
})();

// 使用例子
var Animal = Class.extend({
init: function (opts) {
this.msg = opts.msg;
this.type = "animal";
},
say: function () {
console.log(this.msg + ":i am a " + this.type);
}
});

var animal = new Animal({msg: "hello"}).say();

var Dog = Animal.extend({
init: function (opts) {
Animal.prototype.init.call(this, opts);
this.type = "dog";
}
});

var dog = new Dog({msg: "hi"}).say();

对12行的那个设为true, 和14行的设为false没法理解,中间间隔了一个new this(), 关键就是new this()这里, 原来new this()的时候,会调用构造函数, 在前面设了一个true,下面SubClass里面的init函数就
不会被调用了,在这里只是要生成一个子类的原型对象,没必要调用它的初始化函数。

上面的Class继承机制,Animal继承了Class,在下面的这句话执行完

1
2
3
4
5
6
7
8
9
var Animal = Class.extend({
init: function (opts) {
this.msg = opts.msg;
this.type = "animal";
},
say: function () {
console.log(this.msg + ":i am a " + this.type);
}
});

会给Class对象里面加入一个initPrototype=false的属性, Animal里面没有这个属性, 当执行下面一行

1
var animal = new Animal({msg: "hello"}).say();

会调用Animal的构造器,SubClass.initPrototype=undefined, init也是会调用的

在看Dog这个类,Dog继承了Animal,在下面的语句执行完后

1
2
3
4
5
6
var Dog = Animal.extend({
init: function (opts) {
Animal.prototype.init.call(this, opts);
this.type = "dog";
}
});

会给Animal对象里面加入一个initPrototype=false, 所以不管实例化Class的任何一个子类对象,子类对象
都会调用自己的init方法

javascript组件化