本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第2章,第2.4节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.4 立即执行函数表达式
在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.');
});
}());