закрытие JavaScript на функциональных объектах - PullRequest
0 голосов
/ 11 июня 2018

Почему поведение замыкания здесь не играет роли:

function init(){
  for (var i = 1; i <= 2; i++) {
  
  function timer() {
    var k=i;
    console.log("in timer");
    console.log(timer.i);
    console.log(k);
  }
  
  timer.i = i;
  setTimeout(timer, 0);
  
  }
}
<body onload="init()";>
</body>

Почему timer.i не принимает последнее значение i в стеке внешней функции init?Тем не менее, он принимает внешнее за к.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

На самом деле два timer с.Когда интерпретатор перебирает объявление функции внутри такого цикла, он перезаписывает предыдущее имя функции во внешней области (если такая функция существует).Этот фрагмент может быть понятнее:

for (var i = 1; i <= 2; i++) {
  const oldTimer = window.timer;
  function timer() {
    console.log("in timer");
    console.log(timer.i);
  }
  timer.i = i;
  console.log('oldTimer is ' + oldTimer + (oldTimer ? ' with i of ' + oldTimer.i : ''));
  console.log('is oldTimer the same as the new timer? ' + (oldTimer === timer));
  setTimeout(timer, 1000);
}
console.log('Outside of for loop: timer is ' + typeof timer);

(timer все еще доступен вне цикла for - он добавляется к глобальному объекту.)

0 голосов
/ 11 июня 2018

Объявление функции в EcmaScript 6 теперь имеет блочную область, как и объявления let (с разницей с let в том, что переменная объявлена ​​во внешней глобальной / функциональной области видимости).

Ваш кодглобально эквивалентно

for (var i = 1; i <= 2; i++) {
  let timer = function() {
    console.log("in timer");
    console.log(timer.i);
  }
  timer.i = i;
  setTimeout(timer, 1000);
}

Это означает, что у вас есть другие значения timer.

Обратите внимание, что если вы использовали var вместо let и вместо функцииобъявление, вы бы получили бы дважды один и тот же журнал.

Хорошее чтение: http://2ality.com/2015/02/es6-scoping.html

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

for (var i = 1; i <= 2; i++) {
  let timer_i = i;
  setTimeout(function timer(){
    console.log("in timer");
    console.log(timer_i);
  }, 1000);
}

, которые в этом простом случае могут быть записаны как

for (let i = 1; i <= 2; i++) {
  setTimeout(function timer(){
    console.log("in timer");
    console.log(i);
  }, 1000);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...