范围和访问匿名函数中的外部变量?

时间:2017-10-24 18:04:02

标签: javascript arrays scope

我确定我在这里做一些蠢事,但我不确定是什么。我将匿名函数添加到数组中以供以后执行,并在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();
}

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

这里发生了什么?当您调用数组函数时,它们使用当前值itemAccessUrl,即最后分配的字符串,使用char&#39; b&#39;。这是因为它们的调用在第一个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]();