JavaScript通过对象字面量来创建类(型)

前段时间浏览Nicholas C. Zakas大神的博客,发现一篇很有意思的文章,是Nicholas在看了github上的一个gistjashkenas对JavaScript使用简洁方式创建类的建议)之后写的,主要内容是介绍了一种通过对象字面量来创建类型的方法,下面来说一下吧。

首先贴上jashkenas的伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Color {
constructor(hex) {
...
}

public r = 1;
public g = 1;
public b = 1;

copy(color) {
...
}
setRGB(r, g, b) {
...
}
setHSV(h, s, v) {
...
}
}

上面的类使用构造器和原型方式很容易就可以实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Color(hex){
...
}

Color.prototype.r = 1;
Color.prototype.g = 1;
Color.prototype.b = 1;

Color.prototype.copy = function(color){
...
};
Color.prototype.setRGB = function(r,g,b){
...
};
Color.prototype.setHSV = function(h,s,v){
...
};

但是上面的实现,不大优雅,下面就有了更优雅的实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function type(details){
details.constructor.prototype = details;
return details.constructor;
}
var Color = type({
constructor : function(hex) {
...
},
r: 1, g: 1, b: 1,
copy: function(color) {
...
},
setRGB: function(r, g, b) {
...
},
setHSV: function(h, s, v) {
...
}
});
var mycolor = new Color("ffffff");

type函数很简单,但很优美。看起来很接近最上面的伪代码,也很好的将类的声明封装到一起了。其关键就是理解constructor属性,构造器原型的constructor属性一般情况下都是指向该构造器的。如:

1
2
function f(){}
console.log(f === f.prototype.constructor); //true

而在type函数中通过将传入的对象字面量赋给constructor的原型来实现该循环,然后将constructor返回给调用者,实现了类型的创建。而上面的方法跟下面使用原型方式创建类有一点相似之处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Color(hex){
...
}
Color.prototype = {
constructor : Color,
r : 1, g : 1, b : 1,
copy : function(color){
...
},
setRGB: function(r, g, b) {
...
},
setHSV: function(h, s, v) {
...
}
}

不过还是type函数实现的更加优美简洁。

参考资料

Custom types (classes) using object literals in JavaScript
harmony classes