本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第2章,第2.4节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
在JavaScript中,我们可以在函数声明后立即将其执行,这个技术曾在社区中被称为“自执行匿名函数”,不过冠以这个名称让人们觉得函数能够被递归调用,显然有点不太妥。Ben Alman曾发表了一篇名为“自执行函数表达式”(IIFE)的博文(http://bit.ly/i-ife/),相比之下,人们觉得缩写IIFE显得更为有趣且清晰易懂,现在IEIF一词已经在JavaScript社区中广为使用。IIFE所创建出的临时作用域常常用来作模块封装,jQuery正式使用了IIFE将内部变量与全局作用域隔离开。在IIFE这项技术出现之前,以往的模块封装做法是将方法直接赋值在原型之上。
var Lightbulb = function () { this.isOn = false; }, lightbulb = new Lightbulb(); Lightbulb.prototype.toggle = function () { this.isOn = !this.isOn; return this.isOn; }; Lightbulb.prototype.getState = function getState() { // Implementation... }; Lightbulb.prototype.off = function off() { // Implementation... }; Lightbulb.prototype.on = function on() { // Implementation... }; Lightbulb.prototype.blink = function blink() { // Implementation... }; test('Prototypes without IIFE.', function () { equal(lightbulb.toggle(), true, 'Lightbulb turns on.'); equal(lightbulb.toggle(), false, 'Lightbulb turns off.'); });如你所见,这种模块封装的方式极易导致重复的方法声明,上述示例中Lightbulb.prototype在每一条方法声明中都有出现。IIFE可以将整个作用域封装起来,此时方法可以赋值给普通变量,所有数据被封装在闭包中,代码组织随之也变得更为灵活。
(function () { var isOn = false, toggle = function toggle() { isOn = !isOn; return isOn; }, getState = function getState() { // Implementation... }, off = function off() { // Implementation... }, on = function on() { // Implementation... }, blink = function blink() { // Implementation... }, lightbulb = { toggle: toggle, getState: getState, off: off, on: on, blink: blink }; test('Prototypes with IIFE.', function () { equal(lightbulb.toggle(), true, 'Lightbulb turns on.'); equal(lightbulb.toggle(), false, 'Lightbulb turns off.'); }); }()); 相关资源:JavaScript高级程序设计(附源码)