简体   繁体   中英

Closure confusion in Javascript

Sample 1: http://jsfiddle.net/ufCr8/

function createFunctions() {
    var result = new Array();

    for (var i = 0; i < 10; i++) {
        result[i] = function() {
            return i;
        }();
    }

    return result;
}

var funcs = createFunctions();       
for (var i = 0; i < funcs.length; i++) {
    document.write(funcs[i] + "<br />");
}

Sample 2: http://jsfiddle.net/T5shB/

function createFunctions() {
    var result = new Array();

    for (var i = 0; i < 10; i++) {
        result[i] = function(num) {
            return function() {
                return num;
            };
        }(i);
    }

    return result;
}

var funcs = createFunctions();
for (var i = 0; i < funcs.length; i++) {
    document.write(funcs[i]() + "<br />");
}

Why do those two get different results?

These both work correctly. (And have the same results).

Sample #1:

for (var i = 0; i < 10; i++) {
    result[i] = function() {
        return i;
    }(); // note function application!
}

The anonymous function is executed right then and the result is a number (the current ) value of i each iteration through the loop. This is effectively the same as result[i] = i . Not very exciting. (In the loop that prints the value out, there is no function application, which would be an error as a number if not a function -- in this case it differs from the samples below.)

Sample #2:

for (var i = 0; i < 10; i++) {
    result[i] = function(num) {
        return function() {
            return num;
        };
    }(i);
}

The outer anonymous function which is applied returns a closure which correctly "double-binds" to the current value of i which is passed in as num ( num is actually the bound free-variable). Remember that functions introduce a new scope -- var (or for ) does not.

I suspect the "failing case" would be:

for (var i = 0; i < 10; i++) {
    result[i] = function() {
        return i;
    }; // note function NOT invoked here!
}

...
for (var i = 0; i < funcs.length; i++) {
    document.write(funcs[i]() + "<br />");
}

This will produce "odd results" because it is the same i which is bound in each closure (that is i is the free variable and there is only one i ). Thus when the function is executed it will return the current value of i at the point of execution .

Happy coding


I would recommend reading the Jibbering JavaScript Closure Notes -- it's not the most beginner resource, but I find it accessible and it explains things in sufficient detail. (And is far, far more readable than the ECMAScript specification, IMOHO).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM