繁体   English   中英

Javascript关闭?

[英]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中,存在两个问题:

  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]));
} 

彼得·奥尔森是正确的。 但是,更现代的方法(正确吗?)是使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM