settimeout函数和对象声明的异常行为?

时间:2018-11-22 14:50:29

标签: javascript this settimeout

var user = {

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


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

我得到 user.sayHi 不是函数错误,因为未在setTimeout调用的上下文中定义 user 。 afaik setTimeout上下文是窗口,并且通过 var 定义对象会将对象放入 window对象,然后为什么未定义对象( 1 )?< / p>

2 。改变var让它可以工作!为什么?

3 。键入

var x = user

并将 user.sayHi 更改为 x.sayHi 也可以!我不明白为什么。由于var x和var user对我来说是相同的定义。 请解释

1 个答案:

答案 0 :(得分:-1)

我只是在这里猜测,但认为您是在用户循环中使用超时,例如:

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],
    ),
  );
}

如前所述;之所以起作用,是因为每个操作都有自己的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');

如果我完全错了,那么对此感到抱歉,因为您正在描述一个常见的循环问题,但是发布的代码却不会导致您描述的任何行为,因此不得不猜测。