«это» различное поведение в node и v8 chrome

#javascript #this

#javascript #это

Вопрос:

У меня есть:

 function MyFunc() {
  this.myString = "wooooo";
  setTimeout(function () {
    console.log("printing this.myString", this.myString);
  }, 1000);
}

MyFunc();
 

Если я запускаю этот внутренний узел, я получаю ответ: printing this.myString undefined (кстати node --version gives v12.16.2 )

Если я попробую это сделать в своих инструментах разработки консоли в браузере Chrome, я получу printing this.myString wooooo (кстати, у меня chrome 89.0.4389.90)

Кто-нибудь может объяснить мне, почему это отличается в nodejs и js? Почему у него другое поведение?

Спасибо

Комментарии:

1. Это также происходит внутри node 15.5.1 . Я не думаю, что это проблема V8, поскольку и node, и chrome используют движок v8

2. Похоже, это связано с тем, что this внутри обработчика таймаута ссылается на экземпляр nodejs.org/api/timers.html#timers_class_timeout . Я не смог найти в спецификации ничего о том, что this должно ссылаться на обработчик тайм-аута, поэтому я предполагаю, что решение принимает среда хоста. Браузеры не устанавливают определенное this значение, и Node, похоже, устанавливает указанное значение.

3. На самом деле я пробовал этот урок: youtube.com/watch?v=gigtS_5KOqoamp;t=335s

Ответ №1:

На первый взгляд, обе ссылки на this должны ссылаться на глобальный объект (при условии нестрогого режима), поскольку обе ссылки встречаются в «обычных» функциях.

Это то, что происходит в браузере.

Однако, если вы действительно регистрируете значение this , вы можете увидеть, что оно ссылается на экземпляр Timeout in Node:

 Timeout {
  _idleTimeout: 1000,
  _idlePrev: null,
  _idleNext: null,
  _idleStart: 21,
  _onTimeout: [Function (anonymous)],
  _timerArgs: undefined,
  _repeat: null,
  _destroyed: false,
  [Symbol(refed)]: true,
  [Symbol(kHasPrimitive)]: false,
  [Symbol(asyncId)]: 5,
  [Symbol(triggerId)]: 1
}
 

Очень возможно, что официально не определено, на что this должно ссылаться в обработчике, поэтому среды могут делать все, что захотят в этом отношении.

Комментарии:

1. Кажется, это определяется как window здесь: html.spec.whatwg.org/multipage /. … Хотя никто не говорит, что node должен следовать стандарту DOM.

2. @georg: Ах, и в шаге 7.2 также говорится: «Используйте контекстный прокси-сервер метода в качестве обратного вызова этого значения».. .. Я искал неправильные ключевые слова. Но да, я думаю, Node просто предоставляет setTimeout реализацию для удобства, а не для следования спецификации DOM.