我从概念上很好地理解了闭包,但是出现了一个我不太理解的问题。
当创建一个函数以将某些值传递给内部函数而不在返回时将其绑定(bind)到最外层函数的最终值时,这似乎是不允许的:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
function (x) { // this anonymous function definition...
var item = 'item' + list[x];
result.push(
return function () {
console.log(item + ' ' + list[x]);
};
);
}(i); // and simultaneous invocation...
}
return result;
}
如果我将闭包完全移到 .push() 的调用中,一切都会正常:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
result.push(
function (x) { // wrapper now inside the call to .push()
var item = 'item' + list[x];
return function () {
console.log(item + ' ' + list[x]);
};
}(i) // and called here...
);
}
return result;
}
我想知道的是:当我定义将闭包立即包装在 for 循环内部而不是在 .push() 调用内部的匿名函数时,我违反了什么规则?
最佳答案
通过“不允许”,我假设解释器正在提示语法错误。第一种情况你有什么:
result.push(
return function () {
console.log(item + ' ' + list[x]);
};
);
语法上无效。
但即使你删除了返回:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
function (x) { // this anonymous function definition...
var item = 'item' + list[x];
result.push(
function () {
console.log(item + ' ' + list[x]);
}
);
}(i); // and simultaneous invocation...
}
}
您仍然会收到错误消息。这是因为您没有为 IIFE 指定括号,这意味着 function (x) { ... }()
被视为声明/语句,无论尾随 () 是什么
。但是如果你声明一个函数,你需要指定一个名字,这就是为什么 function
之后的 (
是意外的。如果你想把它当作一个表达式,你必须将其包装在 (...)
中,因此使用 (function (x) { ... })()
。
在第二种情况下,result.push(...)
的参数只能是一个表达式,因此对于 function (x) { .. . }()
需要被解释;它永远不可能是声明,因此它必须是表达式(函数文字或 IIFE)。
打个比方,将 function() { ... }
想象为字符串 "hello"
。你永远不能孤立地使用“hello”
;以下代码在语法上无效:
var x = "foo";
"hello";
这本质上就是您对匿名函数所做的事情:
var x = "foo";
function () {
}
应该用这个函数做什么?它没有分配给任何东西,就像前面示例中的 "hello"
没有分配给任何东西一样。但我们知道函数可以被调用,所以我们用 (function() { ... } ())
所做的就是说“获取我在这里定义的这个函数,然后立即调用它”。它类似于在字符串文字上调用方法:
"abcd".substring(0, 2); // returns "ab"
事实上,您可以使用函数执行类似的操作,我认为这更好地演示了 IIFE 发生的情况:
// logs "hello"
(function() {
console.log("hello");
}).call();
括号是消除歧义并告诉解释器您希望将函数视为表达式/文字而不是声明的一种方法。在上面的示例中,如果删除了周围的括号,您将收到有关意外 (
.
关于javascript - 了解有关闭包的匿名 JavaScript 函数定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36509428/