【问题标题】:JavaScript variable scope inside forEach loopforEach 循环内的 JavaScript 变量范围
【发布时间】:2016-01-14 06:37:50
【问题描述】:

在下面的代码中,forEach 循环使用了回调函数来遍历返回的结果。 forEach 循环中的变量“错误”和回调中的“错误”变量是否相同?

session.getAll(options, function (error, varbinds) {
    varbinds.forEach(function (vb) {
        if (error) 
            console.log('getALL Fail ');
        else              
            console.log(vb.value);            
    });
});

【问题讨论】:

  • 除非内部函数范围引入了新的“错误”变量,否则都是一样的。
  • 您没有定义任何其他error 变量,所以答案是
  • 正如其他人所说,如果没有在循环中使用var 重新定义它,但是forEach 循环不能被中止。因此,在进入循环之前,应该在回调中检查错误。如果出于某种原因需要检查循环,则应使用不同的循环方法。
  • @irom 我意识到这已经有几年的历史了,但我刚刚得到了一个赞成票,当我检查它时,我在这里看到没有接受的答案。我们是否设法提供足够的帮助来检查这一点?

标签: javascript scope


【解决方案1】:

是的,它是同一个变量,如果您使用 var 关键字在 forEach 回调范围内定义另一个 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);            
    });
});

【讨论】:

    【解决方案2】:

    是的,是同一个变量。

    我不确定你知道多少。所以,我要详细解释一下。 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);
    })();
    

    我试图避免在这些示例中使用自调用函数/IIFE,但在最后一个示例中我无法自拔。我认为这是最简单的方法。运行这个,你会得到 7,然后是 5。但是,如果你在那个内部“a”上排除“var”......

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

    你会得到 7, 7。这是因为“var”在内存中创建了一个新空间。此外,如果与更高范围内的某些内容发生名称冲突,它会被覆盖为不同的变量(尽管名称相同)。

    更多示例请见:What is the scope of variables in JavaScript?

    【讨论】:

    • 如果使用let而不是使用var,那么使用let定义的变量在回调中是否可用?
    • @PatS 是的,如果使用了letconst,那么在我的大多数示例中,它们都可以在下面的匿名函数中使用。但是,如果letconstif 语句、for 循环或其他类型的块包装,并且函数是在该块之外定义的,那么它将不可用。这有帮助吗?
    猜你喜欢
    • 2018-08-05
    • 1970-01-01
    • 2012-06-12
    • 2013-08-30
    • 1970-01-01
    • 2013-02-25
    • 2011-09-16
    • 1970-01-01
    相关资源
    最近更新 更多