[英]Javascript closure?
方法1
function transform(ar) {
var alStr = [];
for(var i=0; i<ar.length; i++) {
alStr[i] = (function(v) {
return (function() {
return v;
});
}(ar[i]));
}
return alStr;
}
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
a[1];
b[1]();
方法#2
function transform(ar) {
var alStr = [];
for(var a in ar) {
var O = function() {
return a;
}
alStr.push(O);
}
return alStr;
}
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
a[1];
b[1]();
上述方法用于将数组对象转换为单独的函数,这些函数在执行时返回特定的数组对象。 想知道为什么方法#1有效而方法#2无效。
在方法2中,存在两个问题:
您将返回键名a
而不是数组值ar[a]
。 也就是说,而不是return a;
您想return ar[a];
。
该函数将始终引用循环的最后一个值,因为它引用同一作用域对象。 要创建一个新的作用域对象,您将需要一个闭包,一个with
块或一个绑定函数。
关闭时:
for(var a in ar) {
var O = (function(val) {
return function() {
return val;
}
})(ar[a]);
alStr.push(O);
}
带with
块:
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]();
由于启动关闭具有非常明显的含义,因此这是一个更正确的范例。 但是,使用绑定通常是在函数调用时(在特定上下文中或具有特定规定)专门使用的功能方法。
使用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]());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.