Как я могу вызвать метод объекта внутри setTimeout без потери привязки this?

const bob = {
  name: 'Bob',
  greet: function () {
    console.log(`Hi, I'm ${this.name}`)
  }
};

bob.greet();                   // Hi, I'm Bob
setTimeout(bob.greet, 500);    // Hi, I'm

Я знаю, что в вызове setTimeout this привязан к объекту Window.

0
Bobby Wan-Kenobi 12 Июн 2021 в 21:01

3 ответа

Лучший ответ

Вы можете использовать такую ​​функцию-оболочку:

const bob = {
  name: 'Bob',
  greet: function () {
    console.log(`Hi, I'm ${this.name}`)
  }
};

bob.greet();
setTimeout(() => bob.greet(), 500);

MDN прекрасно объясняет это здесь

3
zb22 12 Июн 2021 в 18:24

У вас здесь проблема с определением объема работ.

Используйте метод .bind чтобы установить область this на объект bob:

const bob = {
  name: 'Bob',
  greet: function () {
    console.log(`Hi, I'm ${this.name}`)
  }
};

bob.greet();                   // Hi, I'm Bob
setTimeout(bob.greet.bind(bob), 500);    // Hi, I'm

.bind возвращает новую функцию с правильной областью видимости.

В качестве альтернативного решения вы можете использовать обратный вызов оболочки:

setTimeout(() => {
  bob.greet();
}, 500);

Обратите внимание на стрелочную функцию, у которой нет области действия this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

3
Marc 12 Июн 2021 в 18:23

Цитата из [MDN] https: //developer.mozilla .org / en-US / docs / Web / JavaScript / Reference / Operators / this

«В большинстве случаев значение этого параметра определяется тем, как вызывается функция (привязка во время выполнения). Его нельзя установить путем присваивания во время выполнения, и оно может отличаться каждый раз при вызове функции. ES5 представил привязку ( ), чтобы установить значение функции this независимо от того, как она вызывается, а в ES2015 были введены стрелочные функции, которые не обеспечивают своей собственной привязки this (он сохраняет значение this охватывающего лексического контекста). "

В дополнение к методу, предоставленному Марком https://stackoverflow.com/a/67951749/14550472

Функция стрелки также может помочь

SetTimeout (() => {bob.greet ()}, 500);

0
nps 12 Июн 2021 в 18:29