Это правильный эквивалент для моей петли? - PullRequest
0 голосов
/ 28 декабря 2018

Я написал простой код 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

Ответы [ 5 ]

0 голосов
/ 17 января 2019

Я ценю все ответы, которые я получил на мой вопрос.Все указывает на случай, когда функция, когда вызывается, обрабатывает среды, в которых она была вызвана и создана.Я прочитал это полезное объяснение в книге «Красноречивый JavaScript» и думаю, что было бы неплохо поделиться им.

«Хорошая ментальная модель - думать о значениях функций как о том, что они содержат как код в их теле, так и средув котором они созданы. При вызове тело функции видит среду, в которой она была создана, а не среду, в которой она вызывается ».~ Eloquent_JavaScript / Closure

0 голосов
/ 28 декабря 2018
"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;
0 голосов
/ 28 декабря 2018

Это потому, что вы на самом деле устанавливаете функцию для возврата значения 3 из-за непериодической среды.Вы должны немного изменить цикл, добавив еще одну переменную, но сначала сделайте так, чтобы ваша функция выглядела следующим образом:

printNumTwo = function() {
    return num;
}

А в вашем смоделированном цикле:

i = 2;
num = i;
printNumTwo = function() {
    return num;
}
i = 3;
0 голосов
/ 28 декабря 2018

Ваш пример плохой, потому что ваш цикл не считается после 2. Так что если ваш цикл выглядит как i <= 3:

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

Вы получите точно такой же результат, как и в примере без цикла, и это потому, чтозакрытия в JavaScript, но return разрывы для цикла.Ваша функция сохраняет ссылку на эту переменную из области видимости.

0 голосов
/ 28 декабря 2018
  1. В вашем коде, не основанном на циклах, printNumTwo не выполняется в той же точке его объявления, и поэтому значение i обновляется перед выполнением, поэтому возвращается значение 3.

{
    let i = 0;
    i = 1;
    i = 2;
    printNumTwo = function () {
        return i;
    }
    i = 3;
}
console.log(printNumTwo());
но если вы запустите следующий код, он должен напечатать 2, поскольку он выполняется до значения, если i установлено в 3

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

Примечание : return в for цикле прерывает дальнейшее выполнение цикла, поэтому даже если ваш первый код имел i <= 3 какв его аварийном состоянии возвращается 2.

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