【问题标题】:very strange behaviour of settimeout function and object declaration?settimeout 函数和对象声明的非常奇怪的行为?
【发布时间】:2018-11-22 14:50:29
【问题描述】:
var user = {

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


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

我得到 user.sayHi 不是函数错误,因为 user 未在 setTimeout 调用的上下文中定义。 afaik setTimeout 上下文是window,通过var定义对象会将该对象放入window object,那为什么是undefined(1)?

2。将 var 更改为 let 将起作用!为什么?

3。输入

var x = user

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

【问题讨论】:

  • 除此之外,您还有其他代码可能碰巧也在使用user 变量吗?似乎必须有其他东西在改变它,使它不再指向这个 sn-p 中定义的对象。
  • 你能用 sn-p 重现这个问题吗?
  • 哎呀。 ty James,确实是另一个脚本干扰,抱歉占用您的时间 :) shy
  • 我猜您正在对用户(多个)使用 for 循环。建议您改用 users.forEach。类似users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

标签: javascript this settimeout


【解决方案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],
    ),
  );
}

如前所述; 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');

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

【讨论】:

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