Свойство `this` не определено внутри setTimeout - PullRequest
0 голосов
/ 20 мая 2018
class Simulator {
  constructor() {
    this.gates = Array();
    this.gates.push(new AndGate(200, 200));
  }
  initialize() {
    let canvas = document.getElementById('board');
    canvas.width = 800;
    canvas.height = 500;
    canvas.setAttribute("style", "border: 1px solid black");
    this.gates.push(new AndGate(100, 100));
  }
  run() {
    setTimeout(this.onLoop, 1000);
  }
  onLoop() {
    for (let gate of this.gates) {
      gate.render();
    }
  }
}
let sim = new Simulator();
sim.initialize();
sim.run();

По какой-то причине JS-версия моего класса TypeScript выдает ошибку в функции onLoop.Сообщает TypeError: this.gates is undefined.Однако, если я получаю доступ к sim (объект Simulator) и вручную получаю доступ к свойству gates, оно определено.Я могу запустить код onLoop вручную с консоли.

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Когда функции передаются по ссылке, они теряют свою ссылку на this.Вы теряете эту ссылку при вызове setTimeout.

. В функциях есть метод bind(), который в основном возвращает новую функцию с исправленной ссылкой на this.

.:

setTimeout(this.onLoop.bind(this), 1000)

В качестве альтернативы, вы также можете передать встроенную функцию стрелки.Функции стрелок не теряют свой this контекст.

setTimeout(() => this.onLoop(), 1000)
0 голосов
/ 20 мая 2018

Когда this.onLoop вызывается в setTimeout, контекст вызова внутри onLoop равен окну , поскольку setTimeout является функцией объекта window .Вы можете исправить это, используя функцию стрелки, которая вызывает onLoop, а не передает onLoop напрямую:

class Simulator {
  constructor() {
    this.gates = Array();
    //this.gates.push(new AndGate(200, 200));
  }
  initialize() {
    //let canvas = document.getElementById('board');
    //canvas.width = 800;
    //canvas.height = 500;
    //canvas.setAttribute("style", "border: 1px solid black");
    // this.gates.push(new AndGate(100, 100));
    this.gates.push({ render: () => console.log('rendered') });
  }
  run() {
    setTimeout(() => this.onLoop(), 1000);
  }
  onLoop() {
    for (let gate of this.gates) {
      gate.render();
    }
  }
}
let sim = new Simulator();
sim.initialize();
sim.run();

Или связав контекст this функции onLoop с созданным объектом:

class Simulator {
  constructor() {
    this.gates = Array();
    //this.gates.push(new AndGate(200, 200));
  }
  initialize() {
    //let canvas = document.getElementById('board');
    //canvas.width = 800;
    //canvas.height = 500;
    //canvas.setAttribute("style", "border: 1px solid black");
    // this.gates.push(new AndGate(100, 100));
    this.gates.push({ render: () => console.log('rendered') });
  }
  run() {
    setTimeout(this.onLoop.bind(this), 1000);
  }
  onLoop() {
    for (let gate of this.gates) {
      gate.render();
    }
  }
}
let sim = new Simulator();
sim.initialize();
sim.run();
...