очень странное поведение функции settimeout и объявления объекта? - PullRequest
0 голосов
/ 22 ноября 2018
var user = {

firstName: 'Вася',
sayHi: function(who) {
    console.log(`firstname - ${this.firstName}: Привет, ${who}`);
    }
}


setTimeout( function() {user.sayHi('asd')}, 2000  );

я получаю user.sayHi не является ошибкой функции, потому что пользователь не определен в контексте вызова setTimeout.afaik контекст setTimeout является окном, и определение объекта с помощью var поместит этот объект в объект окна , тогда почему он не определен ( 1 )?

2 .изменение вар пусть будет работать!почему?

3 .набрав

var x = user

и изменив user.sayHi на x.sayHi также будет работать !!Я не понимаю почему.Поскольку var x и var user являются для меня одинаковыми определениями.Просьба объяснить

1 Ответ

0 голосов
/ 22 ноября 2018

Я просто догадываюсь здесь, но думаю, что вы используете тайм-аут в цикле над пользователями, что-то вроде:

var users = [1, 2];
for (var i = 0; i < users.length; i++) {
  setTimeout(() =>
    console.log(
      'why 2?',
      i,
      'users[2] is undefined',
      users[i],
    ),
  );
}

Если вы используете let, тогда переменная i имеет область видимости блока, каждый цикл получает свой собственный i:

var users = [1, 2];
for (let i = 0; i < users.length; i++) {
  setTimeout(() =>
    console.log(
      'let works:',
      i,
      users[i],
    ),
  );
}

Как указано выше;let работает, потому что каждое изменение получает свою собственную переменную i, но с var есть только window.i, и к тому времени, когда функция setTimeout выполняет window.i, имеет значение 2. Демонстрируется следующим с дополнительным console.log

var users = [1, 2];
for (var i = 0; i < users.length; i++) {
  setTimeout(() =>
    console.log(
      'now you know why 2!',
      i,
      'users[2] is undefined',
      users[i],
    ),
  );
}
console.log('after the loop before the timeout, and i is:',i);

Ваш var-код, вероятно, работает, потому что вы создаете переменную пользователя, которая будет содержать последнего пользователя:

var users = [1, 2];
for (var i = 0; i < users.length; i++) {
  var user = users[i]
  setTimeout(() =>
    console.log(
      'i still is 2',
      i,
      'user is 2 both times as there is only one window.user',
      user,
    ),
  );
}
console.log('after the loop, user is:',user);

Так что в качестве решения вы можете использовать let, но я предпочитаю использовать forEach :

var users = [1, 2];
users.forEach((user) =>
  setTimeout(() =>
    console.log(
      'no more temporary i counter variable, user is:',
      user,
    ),
  ),
);
console.log('after foreach');

Если я полностью ошибаюсь, извините за это, пришлось угадать, поскольку вы описываете проблему с общим циклом, но разместили код, который не вызывает поведение, которое выописать.

...