【问题标题】:Is this the right equivalent for my loop?这是我的循环的正确等价物吗?
【发布时间】:2019-05-26 06:11:56
【问题描述】:

我写了一个简单的 javascript 代码。我的 for 循环迭代一个“let”声明的变量,i 介于 0 和 2 之间。只有当 i == 2 时,才会在循环内声明函数。函数必须返回 i 变量的值。当我从循环外部调用此函数时,该函数返回 i = 2 的值(这对于块范围变量 i 来说很自然。但是,当我将循环代码重写为其非循环等效代码块时,该函数(仍然从块外调用)返回 i = 3 的值。这是怎么回事?

"use strict";
var printNumTwo;

for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());     //returns 2

//  loop equivalent
{
  let i = 0;
  i = 1;
  i = 2;
  printNumTwo = function() {
    return i;
  }
  i = 3;
}
console.log(printNumTwo());     // returns 3

【问题讨论】:

  • 只是为了给下面的答案添加一点样板,您还可以使用自调用匿名函数来返回一个匿名函数其中i 被引用为参数。这样,i 将被隔离到函数的范围内,因此它会记录 2:jsfiddle.net/briosheje/mho6wgxn 此外,你应该看看这个:stackoverflow.com/questions/762011/…
  • 尝试将你的函数变量更改为const printNumTwo

标签: javascript loops for-loop scope let


【解决方案1】:

你的例子很糟糕,因为你的循环在 2 之后没有计数。所以如果你的循环看起来像 i &lt;= 3:

for (let i = 0; i <= 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}

您将得到与非循环示例完全相同的结果,这是因为 javascript 中的闭包但 return 会中断循环。您的函数正在从外部范围保存对该变量的引用。

【讨论】:

  • 感谢您的回复,但 return 不会破坏循环,它只会破坏函数范围。循环仍然继续执行,直到最后一次迭代。另外,我没有使用 i
【解决方案2】:

这是因为由于非循环环境,您实际上将函数设置为返回值 3。你应该稍微改变一下循环,添加另一个变量,但首先让你的函数看起来像这样:

printNumTwo = function() {
    return num;
}

在你的模拟循环中:

i = 2;
num = i;
printNumTwo = function() {
    return num;
}
i = 3;

【讨论】:

    【解决方案3】:
    1. 在您的非基于循环的代码中,printNumTwo 不会在其声明的同一点执行,因此i 的值在执行之前会更新,因此返回值 3。

    {
        let i = 0;
        i = 1;
        i = 2;
        printNumTwo = function () {
            return i;
        }
        i = 3;
    }
    console.log(printNumTwo());
    1. 但如果您运行以下代码,它应该打印 2,因为如果 i 设置为 3,它会在 value 之前执行

    {
        let i = 0;
        i = 1;
        i = 2;
        printNumTwo = (function() {
            console.log(i);
        })()
        i = 3;
    }

    注意return in for 循环会中断循环的进一步执行,因此即使您的第一个代码以i &lt;= 3 作为其中断条件,它也会返回 2。

    for (let i = 0; i <= 3; i++) {
        if (i === 2) {
            printNumTwo = function() {
              return i;
            };
        }
    }
    console.log(printNumTwo())

    【讨论】:

      【解决方案4】:
      "use strict";
      var printNumTwo;
      
      for (let i = 0; i < 3; i++) {
          printNumTwo = function (i) {
            // when references 'i' in this function, 'i' goes to the global scope.
            return i;
          };
          // set the value 3 for 'i' in the global scope
          i = 3;
      }
      console.log(printNumTwo()); // return 3;
      

      试试这个

      "use strict";
      var printNumTwo;
      
      for (let i = 0; i < 3; i++) { 
          printNumTwo = function (i) {
            return i;
          }.bind(null, i); // you set the current value as parameter = 0
          i = 3; // i = 3 and break loop
      }
      console.log(printNumTwo()); // return 0;
      

      试试这个

      "use strict";
      var printNumTwo;
      
      for (let i = 0; i < 3; i++) { 
          let i = 0;
          i = 1;
          i = 2;
          printNumTwo = function (i) {
            return i;
          }.bind(null, i); // you set the current value as parameter = 2
          i = 3; // i = 3 and break loop
      }
      console.log(printNumTwo()); // return 2;
      

      【讨论】:

        【解决方案5】:

        感谢我对我的问题的所有回答。所有这些都指向一个函数在被调用时如何处理它被调用和创建的环境的情况。我在《Eloquent JavaScript》一书中读到了这个有用的解释,觉得可以分享一下,

        “一个好的心智模型是将函数值视为包含其主体中的代码和创建它们的环境。当被调用时,函数主体看到它被创建的环境,而不是其中的环境它被称为。” ~ Eloquent_JavaScript/闭包

        【讨论】:

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