JavaScript variable scope inside forEach loop

2019-06-26 05:15发布

问题:

In the code below there is callback function used with forEach loop going over returned results. Is variable 'error' inside forEach loop and 'error' in callback same variables ?

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

回答1:

Yes, it is the same variable.

I'm not sure how much you know. So, I'm going to explain in detail. Scoping in JavaScript is at the function level*. Think of function definitions as points on a tree. Each point on the tree is a scope. When using a variable, you can only use what is at your current scope and anything available to ancestors going up to the top (global scope). Here are a few rules & examples that may help you better understand:

*UPDATE: ES6 const and let are block-level

Inner functions have access to outer function-level variables

function a() {
    var a = 4;

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

Parameters are defined at the same scope as if they were defined one line below

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

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

Variables in adjacent functions are not accessible

Function a() is the parent. b() and c() are its children. Those children cannot access each other's variables.

function a() {

    function b() {
        var aValue = 2;
    }

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

Location of function definition is what counts

This returns 5 if you run main();:

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

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

Lastly, variable overriding

(function getValue() {
    var a = 5;

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

    alert(a);
})();

I tried to avoid using self-invoking functions/IIFEs for these examples but I just couldn't help myself on this last one. It's the easiest way, I think. Run this and you'll get 7, then 5. But, if you exclude "var" on that inner "a"...

(function getValue() {
    var a = 5;

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

    alert(a);
})();

You'll get 7, 7. This is because "var" creates a new space in memory. Also, if there is a name conflict with something in a higher scope, it gets overridden as a different variable (despite having the same name).

For some more examples, please see: What is the scope of variables in JavaScript?



回答2:

Yes, it's the same variable, it would change if you define another error variable inside the scope of the forEach callback by using the var keyword:

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);            
    });
});