我对这个主题感到困惑,这对我来说非常重要,因为异步函数调用和闭包。我一定错过了javascript函数调用中最重要的部分,到目前为止还无法找到我的问题的答案,因此我希望对你有所帮助!
我的问题假设:
fDynamic
(= 0)i
fDynamic
将内部函数fInnerQueued
排队,将来某个时间点调用。fDynamic
(= 1)i
醇>
这个新的参数值现在对第一个内部函数fInnerQueued
是否可见,它将在最终调用后立即看到更改? ......似乎没有?
似乎函数参数不是自由变量,并且通过异步调用紧密绑定到函数调用范围。
这里是fiddle,这里的本质是:
var j = 0;
var fDynamic = function( i ) {
j = i; // j seems to be a free variable, while i is not?
if( i == 0 ) {
// Delay execution in order to let i change to 1
var fInnerQueued = function() {
console.log(i + ' ('+ j + ')'); //should be "1 (1)" but is "0 (1)"
}
setTimeout( fInnerQueued, 100);
} else {
console.log(i); // is "1 (1)", right!
}
}; // Expected output "1 (1)", "1 (1)" but it is "1 (1)", "0 (1)"...
fDynamic(0);
fDynamic(1);
我也在node.js上对它进行了测试,得到了相同的,有点意想不到的输出。
我浏览了不同的帖子,并没有设法找到答案:
我知道我可以通过创建屏蔽闭包或使用bind来省略麻烦。但我真的很想理解为什么函数参数不被认为是内部函数的自由变量,甚至可以通过异步调用保留它们。
答案 0 :(得分:1)
函数参数是本地范围的变量。
function foo (x) {
}
foo(1);
与
大致相同function foo () {
var x = 1;
}
foo();
不
function foo () {
x = 1;
}
foo();
使用内部函数时,参数将被关闭。
再次调用该函数会在新范围内创建一个新变量。
答案 1 :(得分:0)
这非常简单:i
是一个函数上下文变量,当解析器完成解析它被删除的函数时。 j
是全局上下文中的变量,因此在函数退出时不会删除它。
当您调用该函数两次时,会为每个调用创建一个新的上下文,i
就在此处,因为i
不是一个类变量而是一个参数。第一次打电话时,“老”'保留上下文,以便您的子函数可以在子上下文中执行,其中i
仍为0.当发生这种情况时,第二个调用的i
已经消失,只有j
个全球背景得以保留。
答案 2 :(得分:0)
无论是调用函数同步还是异步方式(例如通过setTimeout)都没有区别,因为Quentin正确指出
函数参数是本地范围的变量。
请参阅the updated fiddle(fStatic被称为fDynamic的2次fStatic)
appendLog("Static Argument, changed within function (expected: 0, 1, 0, 1):");
var fStatic = function( i ) {
var fPrintArg = function() {
appendLog( i );
};
setTimeout(fPrintArg, 100);
fPrintArg();
};
fStatic(0);
fStatic(1);
结果是相同的:i var是每个外部函数调用的范围。