JavaScript变量在forEach循环中的作用域

16
在下面的代码中,使用了回调函数和 forEach 循环来遍历返回的结果。在 forEach 循环内部的变量 'error' 和回调函数中的 'error' 是同一个变量吗?
session.getAll(options, function (error, varbinds) {
    varbinds.forEach(function (vb) {
        if (error) 
            console.log('getALL Fail ');
        else              
            console.log(vb.value);            
    });
});

2
除非内部函数作用域引入了一个新的“error”变量,否则它将是相同的。 - rlemon
1
你没有定义任何其他的“error”变量,所以答案是 - Artyom Neustroev
1
正如其他人所说,如果在循环中没有用 var 重新定义它的话,是可以的。但是 forEach 循环无法被中止。因此,在进入循环之前,应该在回调函数中检查错误。如果出于某种原因需要在循环中进行检查,应该使用不同的循环方法。 - ste2425
@irom 我知道这已经过去几年了,但我刚刚收到了一个赞,当我查看时,我发现这里没有被接受的答案。我们是否成功地提供了足够的帮助来解决这个问题? - BCDeWitt
2个回答

12

是的,它是同一个变量。

我不确定您了解多少。因此,我将详细解释。JavaScript中的作用域在函数级别*. 将函数定义视为树上的点。树上的每个点都是范围。在使用变量时,您只能使用当前范围内的内容以及向上到顶部(全局范围)可用的任何祖先。以下是一些规则和示例,可以帮助您更好地理解:

*更新:ES6 constlet 是块级别的

内部函数可以访问外部函数级别的变量

function a() {
    var a = 4;

    function b() {
        alert(a); /* a = 4 */
    }
}

参数的作用域与它们在下一行定义时相同。

function a(a) {
    // variable "a" is at same scope as the example above

    function b() {
        alert(a);
    }
}

相邻函数中的变量不可访问

函数a()是父级函数。b()和c()是其子函数。这些子函数无法访问彼此的变量。

function a() {

    function b() {
        var aValue = 2;
    }

    function c() {
        alert(aValue); /* "aValue" is undefined here */
    }
}

函数定义的位置很关键

如果你运行 main();,这将返回5:

function getValue(returnFunc) {
    var a = 7;
    alert(returnFunc());
}

function main() {
    var a = 5;
    getValue(function() { return a; }); // anonymous function becomes "returnFunc"
}

最后,变量覆盖

(function getValue() {
    var a = 5;

    (function () {
        var a = 7;
        alert(a);
    })();

    alert(a);
})();

我尝试避免在这些示例中使用自执行函数/IIFEs,但在最后一个示例中我无法自拔。我认为这是最简单的方法。运行这个函数你会得到7和5。但是,如果你在内部的"a"上排除"var"关键字...

(function getValue() {
    var a = 5;

    (function () {
        a = 7;
        alert(a);
    })();

    alert(a);
})();

你会得到7, 7。这是因为"var"在内存中创建了一个新的空间。另外,如果与更高作用域中的某个变量名称发生冲突,则将其覆盖为另一个变量(尽管名称相同)。

有关更多示例,请参见:JavaScript 变量的作用域是什么?


如果使用 let 代替 var,那么用 let 定义的变量在回调函数中是否可用? - PatS
1
@PatS 是的,如果使用了letconst,它们在我这里的大多数示例中在匿名函数中是可用的。但是,如果letconst被包装在if语句、for循环或其他类型的块中,并且函数定义在该块之外,则它将不可用。这有帮助吗? - BCDeWitt

4

是的,这是同一个变量,如果你在forEach的回调函数作用域内使用var关键字定义另一个error变量,则会更改该变量:

session.getAll(options, function (error, varbinds) {
    varbinds.forEach(function (vb) {
        if (error) //Same error as the error parameter above
            console.log('getALL Fail ');
        else              
            console.log(vb.value);            
    });
});

session.getAll(options, function (error, varbinds) {
    varbinds.forEach(function (vb) {
        var error = false; //New error for this closure.
        if (error) 
            console.log('getALL Fail ');
        else              
            console.log(vb.value);            
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接