首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript不支持带有局部变量的闭包吗?

JavaScript不支持带有局部变量的闭包吗?
EN

Stack Overflow用户
提问于 2009-03-13 16:27:25
回答 7查看 18.4K关注 0票数 60

我对这段代码感到非常困惑:

代码语言:javascript
复制
var closures = [];
function create() {
  for (var i = 0; i < 5; i++) {
    closures[i] = function() {
      alert("i = " + i);
    };
  }
}

function run() {
  for (var i = 0; i < 5; i++) {
    closures[i]();
  }
}

create();
run();

根据我的理解,它应该输出0,1,2,3,4 (这不就是闭包的概念吗?)。

相反,它会打印5,5,5,5,5

我试过Rhino和Firefox。有人能给我解释一下这种行为吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-03-13 16:57:48

通过添加额外的匿名函数修复了Jon的答案:

代码语言:javascript
复制
function create() {
  for (var i = 0; i < 5; i++) {
    closures[i] = (function(tmp) {
        return function() {
          alert("i = " + tmp);
        };
    })(i);
  }
}

解释是JavaScript的作用域是函数级的,而不是块级的,创建闭包只是意味着将封闭的作用域添加到封闭函数的词法环境中。

循环结束后,函数级变量i的值为5,这就是内部函数“看到”的。

附注:您应该注意创建不必要的函数对象,特别是在循环中;它的效率很低,如果涉及DOM对象,则很容易创建循环引用,从而在Internet Explorer中引入内存泄漏。

票数 61
EN

Stack Overflow用户

发布于 2009-03-13 16:39:44

我想这可能是你想要的:

代码语言:javascript
复制
var closures = [];

function createClosure(i) {
    closures[i] = function() {
        alert("i = " + i);
    };
}

function create() {
    for (var i = 0; i < 5; i++) {
        createClosure(i);
    }
}
票数 9
EN

Stack Overflow用户

发布于 2009-03-13 16:42:50

解决方案是让一个自动执行的lambda包装您的数组推送。您还可以将i作为参数传递给lambda。在自执行的lambda中,i的值将隐藏原始i的值,一切都将按预期运行:

代码语言:javascript
复制
function create() {
    for (var i = 0; i < 5; i++) (function(i) {
        closures[i] = function() {
            alert("i = " + i);
        };
    })(i);
}

另一种解决方案是创建另一个闭包,该闭包捕获i的正确值,并将其赋给另一个变量,该变量将在最终的lambda中“被捕获”:

代码语言:javascript
复制
function create() {
    for (var i = 0; i < 5; i++) (function() {
        var x = i;

        closures.push(function() {
            alert("i = " + x);
        });
    })();
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/643542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档