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

2011-11-15

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

首先贴上jashkenas的伪代码

class Color {
  constructor(hex) {
    ...
  }

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

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

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

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){
  ...
};

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

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属性一般情况下都是指向该构造器的。如:

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

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

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