Javascript闭包?
方法#1 上述方法用于将数组对象转换为单个函数,这些函数在执行时返回特定的数组对象。想知道为什么方法1有效而方法2无效。在方法2中有两个问题:Javascript闭包?,javascript,closures,Javascript,Closures,方法#1 上述方法用于将数组对象转换为单个函数,这些函数在执行时返回特定的数组对象。想知道为什么方法1有效而方法2无效。在方法2中有两个问题: 返回的是键名a,而不是数组值ar[a]。也就是说,而不是返回a您想要返回ar[a] 函数将始终引用循环通过的最后一个值,因为它引用相同的范围对象。要创建一个新的范围对象,您需要一个闭包、一个带有块的或一个绑定函数 结束时: for(var a in ar) { var O = (function(val) { return functio
a
,而不是数组值ar[a]
。也就是说,而不是返回a
您想要返回ar[a]代码>
或一个绑定函数
for(var a in ar) {
var O = (function(val) {
return function() {
return val;
}
})(ar[a]);
alStr.push(O);
}
使用带有块的:
for(var a in ar) {
with({val: ar[a]}) {
alStr.push(function() {
return val;
});
}
}
使用绑定函数:
for(var a in ar) {
var O = function(x) { return x; };
alStr.push(O.bind(null, arr[a]));
}
彼得·奥尔森是对的。但是,更现代(正确的?)的方法是使用function.bind(obj,val)
。最近引入的function.bind
允许您在特定上下文中按值传递变量。阅读更多
你可以这样写:
function transform(ar) {
var alStr = [];
var O = function(x) { return x }
for(var a in ar) {
alStr.push(O.bind(null, ar[a]));
}
return alStr;
}
var a = ["a", 24, 12345];
var b = transform(a);
console.log(a[2]);
b[2]();
这是一个更正确的范例,因为启动闭包具有非常明确的含义。然而,使用bind往往是一种函数方法,在函数调用时(在特定的上下文中或具有特定的规定)要特别使用
使用with块也有一些缺点(关于它有很多问题)
奖金:如果希望b
也表示a
数组的后续更改,此解决方案解决了该问题:
function transform(ar) {
var alStr = [];
var O = function(x) { return ar[x] }
for(var a in ar) {
alStr.push(O.bind(null, a));
}
return alStr;
}
var a = ["a", 24, 12345];
var b = transform(a);
console.log(a[2]);
console.log(b[2]());
console.log("*********");
a[2] = "new value!";
console.log(a[2]);
console.log(b[2]());
只有新函数引入新变量。。这个问题提得太多了。搜索“javascript循环最后一个值”或类似内容。请参阅以获得良好的解释。在非工作代码中,将var a
放在for
循环之前,这样可以更好地反映现实。对于for
语句,没有本地变量,因为在JavaScript中,作用域总是由函数定义的。这意味着在for
循环中创建的所有函数都引用同一个a
变量,该变量是transform
函数的本地变量。有关javascript中变量范围和提升的参考,请参阅。@32bitkid:您的两个链接都非常有用,非常感谢。第1点是我这边的输入错误,抱歉。仍在努力理解第二点。尽管这个答案是正确的,但我认为这里应该首选函数.bind
。@daviditarenco很好,我更新了我的答案,并将+1添加到了你的答案中。使用了块技巧。这是我偶尔想到的一句话,但很少(从未)使用。我可能会更多地使用它,“带闭包”的例子实际上没有闭包。OP的第二个示例中的闭包才是问题所在,使用立即调用的函数表达式会破坏闭包。
function transform(ar) {
var alStr = [];
var O = function(x) { return x }
for(var a in ar) {
alStr.push(O.bind(null, ar[a]));
}
return alStr;
}
var a = ["a", 24, 12345];
var b = transform(a);
console.log(a[2]);
b[2]();
function transform(ar) {
var alStr = [];
var O = function(x) { return ar[x] }
for(var a in ar) {
alStr.push(O.bind(null, a));
}
return alStr;
}
var a = ["a", 24, 12345];
var b = transform(a);
console.log(a[2]);
console.log(b[2]());
console.log("*********");
a[2] = "new value!";
console.log(a[2]);
console.log(b[2]());