外部函数的函数参数是否为异步内部函数改变?

时间:2014-05-07 08:32:52

标签: javascript function asynchronous arguments closures

我对这个主题感到困惑,这对我来说非常重要,因为异步函数调用和闭包。我一定错过了javascript函数调用中最重要的部分,到目前为止还无法找到我的问题的答案,因此我希望对你有所帮助!

我的问题假设:

  1. 使用一些参数fDynamic(= 0)
  2. 调用外部函数i
  3. fDynamic将内部函数fInnerQueued排队,将来某个时间点调用。
  4. 同时使用不同的参数fDynamic(= 1)
  5. 再次调用外部函数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来省略麻烦。但我真的很想理解为什么函数参数不被认为是内部函数的自由变量,甚至可以通过异步调用保留它们。

3 个答案:

答案 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是每个外部函数调用的范围。