【问题标题】:JavaScript Lexical environmentJavaScript 词法环境
【发布时间】:2020-08-06 07:02:02
【问题描述】:

我听说每个函数都记得(?)该函数创建的词法环境。

在这段代码中,函数function () { console.log(i);}, 我想知道这个函数是在哪里创建的。如果某个函数是另一个函数的参数,那么 created(?)/generated 点在哪里?

function countSeconds(howMany) {
  for (var i =1; i <= howMany; i++) {
    setTimeout(function () {
      console.log(i);
    }, i * 1000 );
  }
};

【问题讨论】:

  • 这是一个函数表达式。它是在评估 setTimeout 的参数列表时创建的。
  • @Andreas 您将词法环境(确实 所有 闭包都继承)与只有箭头函数从其范围继承的 thisValue 混淆了/跨度>

标签: javascript function ecmascript-6 closures


【解决方案1】:

在这段代码中,函数function () { console.log(i);},我想知道这个函数是在哪里创建的。

这个函数被定义为function expression。这样的表达式在运行时进行评估,就像表达式{ y: x*x } 将在运行时进行评估一样。但在这种情况下,评估结果是一个函数对象。然后将该函数作为参数传递给setTimeout。这意味着创建的函数与 for 循环的迭代次数一样多。

现在,即使函数表达式在setTimeout 被执行的那一刻被计算,这并不意味着函数的body 在同一时间被执行。它不是。它只会在超时到期时执行。那时函数体执行,并且只有在那个时候它会评估该代码中使用的表达式,例如变量i。在您的示例中,变量 i 将已经达到值 howMany+1,因为 for 循环在计时器到期之前已经运行完成,并且回调被调用。

如果您想避免这种情况,请为 for 循环的每次迭代使用单独的变量 i。使用let 而不是var,您可以创建这些不同的变量,这些变量只存在于for 循环块内。因此,每个函数表达式都将引用其“自己的”i

function countSeconds(howMany) {
  for (let i =1; i <= howMany; i++) {
    setTimeout(function () {
      console.log(i);
    }, i * 1000 );
  }
};

countSeconds(10);

【讨论】:

    【解决方案2】:

    如果某个函数是另一个函数的参数,那么创建的(?)/生成的点在哪里?

    与函数调用的所有参数一样,它们在函数被调用之前被评估。您可以用两个临时变量将其重写为等效的

    function countSeconds(howMany) {
      for (var i=1; i<=howMany; i++) {
        const __arg1 = function() {
          console.log(i);
        };
        const __arg2 = i * 1000;
        setTimeout(__arg1, __arg2);
      }
    }
    

    函数在计算函数表达式时创建。

    (另请注意,此代码具有famous closure in a loop problem。)

    【讨论】:

      【解决方案3】:

      我不明白你的意思?

      你的意思是console.log()函数定义在哪里?

      class console {
         log(text) {
           [I dont know]
         }
      }
      

      那你可以让“console.log()”从Claas控制台调用函数“Log”吗?你是这个意思吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        相关资源
        最近更新 更多