更新:
我发现了这个问题,我确实在其中详细介绍了闭包,并用很少的图纸来阐明如何使用闭包和函数范围(以及它们如何为您提供帮助)。
IIFE 作为函数对象,是在 JS中创建真实作用域的唯一方法。它们到处都在使用。你曾经使用过 jQuery 或其他一些库吗?那么你已经使用了使用 IIFE 的代码。
曾经研究过 node.js 吗?那么你可能会遇到一种叫做“模块模式”的东西。
如果您尝试编写自己的构造函数,您可能想知道如何在对象上拥有某种私有属性。答案是 IIFE 的一次又一次。
另外:DOM api 并不是世界上最快的东西。拥有一个包含硬编码document.getElementById
调用的函数意味着,每次调用该函数时,都会遍历 DOM。这并不理想。解决此问题的一种快速简便的方法是:
var f = (function(domReference)
{
var visible = !!(domReference.style.visibility === 'block')
return function()
{//has access to vars and arguments of outer function
domReference.style.visibility = visible ? 'none' : 'block';
visible = !visible;
}
}(document.getElementById('foobar'));
但也许最好、最常见的例子是循环中的超时/间隔:
for (var i=0;i<10;i++)
{
setTimeout((function(currentI)
{
return function()
{
console.log(currentI);
console.log(i);
}
}(i)), 1000);
在这里,currentI
将记录 0、1、2... 等等,而i
将始终记录10
. 原因是超时回调没有得到它自己的' 值副本,但它引用了变量。该变量可以根据需要更改其值,当调用超时回调时,它将记录最后分配的任何值。定义回调时未分配值。i
i
i
i
没有过多的细节,我提到了对象的私有属性。好吧,这里有一个例子让你弄清楚为什么 IIFE 和函数范围是至关重要的,以及 JS 的一个令人难以置信的强大功能:
var MyConstructor = (function()
{
return function(foo, bar)
{
var initState = Array.prototype.slice.apply(arguments, [0]);
this.getInit = function()
{
return initState;
};
this.foo = foo;
this.bar = bar;
}
}());
(function(constant)
{
var F = function(args)
{
return MyConstructor.apply(this, args);
},
checkVar = constant || 'default constant value';
F.prototype = MyConstructor.prototype;
MyConstructor.prototype.getConstant = function()
{
if (constant !== checkVar)
{//bad example
return checkVar;
}
return constant;
};
MyConstructor.prototype.regularMethod = function()
{
return this.foo;
};
MyConstructor.prototype.copyFromInitState = function()
{
return new F(this.getInit());
};
}('Immutable value'));
玩得开心……:P