回调函数访问闭包变量

callback function access to closure variables?

本文关键字:变量 闭包 访问 函数 回调      更新时间:2023-09-26

下面这段代码有一个bug,但是它引发了一个有趣的问题。它使用的是angular的$http服务,它会返回一个promise。解析后,回调函数不能访问s1变量。

    var ids = [];
    ids = ['81074'];
    // show what's in
    for (var s=0;s<ids.length;s++) {
        var s1 = s;
        $http.get('http://mydomain.com/api/catalog/product/' + ids[s]).
                 success(function(data) {
        // console.log(s1); <--- reference error
            $scope.products[s].setProductData(data);
        }).error(function(err){
                console.log('--------- error',err);
            });
    };

s1给出了ReferenceError: s1在调试器中没有定义

有趣的是,它确实可以访问for循环变量s,它总是为1 -正如预期的那样,因为承诺在其递增后得到解决(因此bug BTW)

有人能解释一下为什么吗?

感谢Lior

这是for循环中异步回调的典型问题。ss1只声明一次。即使你在循环中声明了var s1;, JavaScript也没有块作用域,所以它是不相关的。

这意味着所有迭代都共享相同的变量ss1,因此当回调完成时,$scope.products[s]正在查找ids.length + 1的产品。

相反,做的事:

var ids = [];
ids = ['81074'];
function launchRequest(s) {
    $http.get('http://example.com/api/catalog/product/' + ids[s]).success(function (data) {
        $scope.products[s].setProductData(data);
    }).error(function (err) {
        console.log('--------- error', err);
    });
}
// show what's in
for (var s = 0; s < ids.length; s++) {
    launchRequest(s);
}

…它在launchRequest中引入了一个新的函数级作用域,这意味着当回调解析时,s仍然是函数中的s