Javascript JS:哪些/如何在闭包中存储变量?
考虑以下代码:Javascript JS:哪些/如何在闭包中存储变量?,javascript,node.js,closures,Javascript,Node.js,Closures,考虑以下代码: var a = [ { a: 'I' }, { a: 'II' }, { a: 'III' } ]; for( var i=0; i<a.length; i++ ){ var j = i; var x = a[ i ]; x.bb = function(){ x.b = "-" + x.a + "-"; }
var a = [ { a: 'I' }, { a: 'II' }, { a: 'III' } ];
for( var i=0; i<a.length; i++ ){
var j = i;
var x = a[ i ];
x.bb = function(){
x.b = "-" + x.a + "-";
}
x.cc = function(){
a[ i ].c = "-" + a[ i ].a + "-";
}
x.dd = function(){
a[ j ].d = "-" + a[ j ].a + "-";
}
}
for( var i=0; i<a.length; i++ ){
a[i].bb();
a[i].cc();
a[i].dd();
}
console.log( a );
所以只有cc()完成了我想要做的事情
我现在的问题是:
i
被存储为常量,j
和x
被存储为对局部变量的引用,这些局部变量在for循环迭代时被更改。但这是为什么?这是我的错误。该代码之所以有效,是因为第二个和第一个i
相同李>
bb()
的方法,它可以存储对a[i]
的引用,这样我就不必使用索引了谢谢 您需要记住,JavaScript没有块作用域(无论如何,现在还没有),相反,一切都在“函数”级别。也就是说,所有变量的作用域都是其最新的函数定义 变量是使用
var
语句声明的,根据您的代码,您拥有的每个变量的作用域都是此代码的外部容器。换句话说,如果此代码位于节点模块中,则此处的所有变量的作用域都是整个模块。因此,尽管在for
循环中定义的函数都是闭包(因为所有JS函数都是闭包),但它们仍然只是使用模块中定义的变量,因为JS不需要进一步查看
为了说明问题1的答案,请考虑以下内容:
var o = {};
var x = 1;
function foo() {
var x = 2;
o.bar = function() {
console.log(x);
}
}
o.bar(); // will output "2" because of the closure created in `foo()`
至于你的第二个问题,因为a[i]是一个对象,所以你分配给该对象的任何变量(在本例中,
x
)都将是一个引用,所有引用都将指向内存中的同一个对象。我不是您试图用bb()
实现的目标,而是您使用x
来“存储对[I]的引用”。也许你有一个更具体的例子?这里没有闭包。很抱歉,用错了词。那么,您如何命名这些存储对周围作用域的引用的函数呢?闭包通过保存对外部变量环境的引用来工作。在这种情况下,所有函数都具有相同的外部变量环境(即全局范围)。因此,当您在函数中引用i
和j
时,您指的是存在于函数外部的全局i
和j
。如果您想要捕获一个值,而不是一个(可能变化的)变量的引用,请参阅a-h。真正让我困惑的是,它似乎与i
一起工作。但现在我注意到,我的第一个I
和第二个I
是一样的(我希望一些理智的解释器会抱怨第二个var
),在第二个循环中使用另一个变量会导致失败。@Scheintod仅供参考,重复的var
语句是明确允许的(或者是允许忽略的)在ES5规范中,.@apsillers提出了一个很好的观点,这就是为什么您应该始终在JavaScript中使用它,这将迫使解释器将重复的var
语句作为错误(应该是这样的)!这很简单,只需将“use strict;”“
放在函数/模块的顶部即可。
var o = {};
var x = 1;
function foo() {
var x = 2;
o.bar = function() {
console.log(x);
}
}
o.bar(); // will output "2" because of the closure created in `foo()`