В JavaScript много странностей и сложного для понимания поведения. Есть веселые разговоры, такие как WTFJS и WAT, которые высмеивают JavaScript за его странности.

Поскольку я занимаюсь рефакторингом, мне приходится учитывать множество странных, а иногда и забавных сторон JavaScript. Я поделюсь некоторыми из удивительных поведений, с которыми сталкиваюсь, поэтому, если вы их увидите (чего, надеюсь, никогда не увидите), это может намекнуть на то, что происходит.

Этот пост в блоге исследует невинное заявление:

// ... some code
helloWorld;

Вы можете интуитивно подумать, что здесь ничего не должно происходить — кажется, что оператор ничего не делает, потому что здесь нет очевидного вызова функции.

Однако он может делать что угодно, например, печатать «Hello World!» к консоли.

// ... some code
helloWorld;           // prints "Hello World!"

Как это вообще возможно?

Получается, что глобальные переменные (в данном случае helloWorld) являются свойствами глобального объекта. И свойства в JavaScript не обязательно должны быть простыми значениями. Их можно реализовать с помощью геттеров и сеттеров, которые могут выполнять код. Поскольку в современных механизмах JavaScript глобальный объект наследуется от Object.prototype, добавление свойств к Object.prototype создает свойства глобального объекта.

Здесь helloWorld определяется как геттер:

Object.defineProperty(Object.prototype, 'helloWorld', {
  get() { console.log("Hello World!"); },
});
helloWorld;           // prints "Hello World!"

К счастью, это может произойти только с глобальными переменными, а не с параметрами или локальными переменными.

Object.defineProperty(Object.prototype, 'helloWorld', {
  get() { console.log("Hello World!"); },
});
const a = helloWorld; // getter is evaluated, prints "Hello World!"
a;                    // does nothing

Я узнал об этом странном поведении в сообщении в блоге о полифилле globalThis. В полифилле для доступа к глобальному объекту this в различных средах, таких как браузеры, веб-воркеры, фреймы, модули Node.js и ES, используется метод получения глобальных свойств. Посмотрите, если хотите узнать больше!