对象即时初始化

还有另外一种可以避免污染全局作用域的方法,和前面描述的即时函数相似,叫做“对象即时初始化”模式。这种模式使用一个带有init()方法的对象来实现,这个方法在对象被创建后立即执行。初始化的工作由init()函数来完成。

下面是一个对象即时初始化模式的例子:

  1. ({
  2. // 这里可以定义一些设置项,比如常量
  3. maxwidth: 600,
  4. maxheight: 400,
  5. // 你也可以定义一些方法
  6. gimmeMax: function () {
  7. return this.maxwidth + "x" + this.maxheight;
  8. },
  9. // 初始化
  10. init: function () {
  11. console.log(this.gimmeMax());
  12. // 更多的初始化任务……
  13. }
  14. }).init();

在语法上,当你使用这种模式的时候就像在使用对象字面量创建一个普通对象一样。不同之处在于,需要将对象字面量用括号括起来,这样能让JavaScript引擎知道这是一个对象字面量,而不是一个代码块(if或者for循环之类)。在括号后面,紧接着就执行了init()方法。

你也可以将对象字面量和init()调用一起写到括号里面。简单地说,下面两种语法都是有效的:

  1. ({...}).init();
  2. ({...}.init());

这种模式的好处和即时函数模式是一样的:在做一些一次性的初始化工作的时候保护全局作用域不被污染。从语法上看,这种模式似乎比即时函数要复杂一些,但是如果你的初始化工作比较复杂(这种情况很常见),它会给整个初始化工作一个比较清晰的结构。比如,一些私有的辅助性函数可以被很轻易地看出来,因为它们是这个临时对象的属性,但是如果是在即时函数模式中,它们很可能只是一些散落的函数。

这种模式的一个弊端是,JavaScript压缩工具可能不能像压缩一段包裹在函数中的代码一样有效地压缩这种模式的代码。这些私有的属性和方法不被会重命名为一些更短的名字,因为从压缩工具的角度来看,保证压缩的可靠性更重要。在写作本书的时候,Google出品的Closure Compiler的“advanced”模式是唯一会重命名立即初始化的对象的属性的压缩工具。一个压缩后的样例是这样:

  1. ({d:600,c:400,a:function(){return this.d+"x"+this.c},b:function(){console.log(this.a())}}).b();

这种模式主要用于一些一次性的工作,并且在init()方法执行完后就无法再次访问到这个对象。如果希望在这些工作完成后保持对对象的引用,只需要简单地在init()的末尾加上return this;即可。