【问题标题】:Scope and accessing outside variables in anonymous functions?在匿名函数中作用域和访问外部变量?
【发布时间】:2017-10-24 18:04:01
【问题描述】:

我确定我在这里做了一些愚蠢的事情,但我不确定是什么。我将匿名函数添加到数组中以供以后执行,并在 for 循环中创建它们,其中的变量会改变每次迭代。

我希望记录的值是: https:server.net/a https:server.net/b

但我得到的是: https:server.net/b https:server.net/b

看起来可能当我重新定义函数时它会覆盖它的最后一个版本,但我不知道为什么。我认为每个匿名函数都会有所不同。

为什么?我在这里做错了什么?

这里有一些示例代码:

f = [];
items = ['a', 'b'];
for(var i = 0; i < items.length; i++){
    var itemID = items[i];
    var itemAccessUrl = `https://server.net/${itemID}`;

    var func = function(){ 
        console.log(itemAccessUrl);
    };
    f.push(func);
}

console.log(f.length);
for(var j = 0; j < f.length; j++){
    func();
}

【问题讨论】:

标签: javascript arrays scope


【解决方案1】:

这是因为var 范围界定的性质。 var 不是块作用域,它是“提升的”,就像你在函数顶部声明它一样。

您可以使用let 来声明 itemAccessUrl,而不是使用块作用域的 var,但这取决于您需要的浏览器支持。 (话虽如此,您使用的是模板化字符串,所以应该没问题)

【讨论】:

  • 如果我将 itemID 和 itemAccessUrl 更改为 let's 而不是 var's,问题仍然存在。如果我将它更改为 func,当我稍后执行它时,我会收到错误:“函数未定义”。我需要用其他方式调用它吗?
  • 这是第二个 for 循环中的行。将其更改为f[j]();。否则,您将在循环中调用相同的函数几次
【解决方案2】:

这里发生了什么?当您调用数组的函数时,它们使用 itemAccessUrl 的当前值,即最后分配的字符串,带有 char 'b'。这是因为它们的调用发生在第一个 for 循环完成之后。

你可以使用闭包:

f = [];
items = ['a', 'b'];
for(var i = 0; i < items.length; i++){
    var itemID = items[i];
    var itemAccessUrl = `https://server.net/${itemID}`;

    var func = (function(param) {
        return function () {
            console.log(param);
        };
    })(itemAccessUrl);
    f.push(func);
}

console.log(f.length);
for(var j = 0; j < f.length; j++){
    f[j]();
}

或将你的函数绑定到当前参数:

f = [];
items = ['a', 'b'];
for(var i = 0; i < items.length; i++){
    var itemID = items[i];
    var itemAccessUrl = `https://server.net/${itemID}`;

    var func = (function (param) {
        console.log(param);
    }).bind(null, itemAccessUrl);
    f.push(func);
}

console.log(f.length);
for(var j = 0; j < f.length; j++){
    f[j]();
}

此外,您必须更改第二个循环,调用 f[j]();

【讨论】:

    猜你喜欢
    • 2020-08-19
    • 2012-01-14
    • 2013-08-16
    • 2014-04-09
    • 2012-12-31
    • 1970-01-01
    相关资源
    最近更新 更多