2

方法#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 无效。

4

2 回答 2

4

在方法#2中有两个问题:

  1. 您正在返回键名 ,a而不是数组值 ,ar[a]。也就是说,而不是return a;你想要return ar[a];的 .

  2. 该函数将始终引用循环通过的最后一个值,因为它引用了相同的作用域对象。要创建一个新的作用域对象,您需要一个闭包、一个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]));
} 
于 2012-08-06T01:13:10.543 回答
3

彼得奥尔森是正确的。但是,更现代(正确?)的方法是使用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]());
于 2012-08-06T01:34:20.833 回答