Можем ли мы изменить контекст выполнения JavaScript браузера с объекта Window на что-то другое?

Предположим, у меня есть устаревший файл с именем module.js, который выглядит следующим образом:

a=1;

Это по умолчанию присоединяется к объекту window, загрязняющему область global (фактически window), когда вы выполняете его в браузере.

Могу ли я вместо этого прикрепить его к другому объекту без изменения содержимого исходного кода?

Поскольку единственная реальная проблема — это контекст выполнения и ничего больше, идеальным решением было бы что-то вроде этого:

change execution context from window to module object;
execute the code;
change execution context from module to window object;

Если это невозможно, добавление оболочек (таких как IIFE) в исходный код допустимо, если внутреннее содержимое не изменяется. Для изменения внутреннего содержимого требуется полное сканирование кода, что дорого.

Я могу, например, обернуть это в такую ​​функцию (✓):

function module()
{
    a=1;
}

Если он выполняется в строгом режиме, я могу избежать загрязнения глобальной области видимости. Однако я не могу получить объект.

Я не хочу делать что-то вроде этого (✗):

module = function module()
{
    return a=1;
}

потому что нам нужно добавить return везде, где есть присваивание, а это означает сканирование всего кода.

Я просто пытаюсь найти способы улучшить устаревший код, предназначенный для браузера, с минимальными усилиями.


person Nishant    schedule 05.05.2018    source источник
comment
Как вы загружаете код? Как вы выполняете функцию модуля?   -  person Luca Rainone    schedule 05.05.2018
comment
@Luca Rainone, используя тег script, поскольку он предназначен для использования в браузере.   -  person Nishant    schedule 05.05.2018
comment
Насколько велик ваш унаследованный код? И какие изменения вы хотите сделать? Рассматривали ли вы инструменты рефакторинга, такие как jscodeshift или graspjs немного сложны, но очень эффективны, позволяя вам писать преобразования и применять их ко всей кодовой базе.   -  person Moti Korets    schedule 05.05.2018
comment
Спасибо за записи @MotiKorets. Это теоретический вопрос, у меня нет немедленного варианта использования, но я просто хотел понять, как решить эту проблему.   -  person Nishant    schedule 05.05.2018
comment
Нет чистого пути. Вы должны изменить функцию во время выполнения (например, с помощью module.toString().replace(/*somethingofmagic*/) и поместить ее в eval. Грязно и опасно. Так что лучшим способом будет рефакторинг с помощью какого-либо инструмента, как было предложено   -  person Luca Rainone    schedule 05.05.2018
comment
Веб-воркеры сделают это, и однажды эту роль могут взять на себя реалмы. Но нет, вы действительно должны писать чистый код в первую очередь.   -  person Bergi    schedule 05.05.2018
comment
В качестве альтернативы используйте строгий режим, чтобы вы, по крайней мере, получили исключение, а глобальная область не загрязнялась случайными присваиваниями.   -  person Bergi    schedule 05.05.2018


Ответы (1)


Ответ на первый вопрос: нет, нельзя изменить контекст выполнения по умолчанию в браузере. window — это специальная переменная, и присвоение ей чего-либо еще не изменит контекст выполнения по умолчанию. См. Глобальный объект в MDN. А вот иллюстрация

(function() {
  window = {}
  a = 5 // leaking declaration
  var b = 10
})()

console.log(a) // a is on global scope
//console.log(b) // exception b is not defined in this scope
var b = 5
window = new Object()
window.c = 5
console.log(window.b) // 5 
console.log(c)  // 5

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

  • jscodeshift позволяет вам писать codemods функции, которые получают код и применяют к нему преобразования. Это, пожалуй, самый мощный инструмент в этой категории.
  • ESLint позволяет вам устанавливать правила (например, без глобальных переменных) и иметь --fix, который будет применять автоматические исправления в некоторых случаях, таких как переход от одинарных кавычек к двойным кавычкам (в основном это относится к правилам, связанным со стилем).
  • prettier — форматировщик кода, который занимается только внешним видом кода: отступами, пробелами и т. д.
  • AST Explorer онлайн-инструмент, который позволяет вам увидеть внутренности всех вышеперечисленных инструментов, очень полезный, чтобы понять, как он работает, и попробовать код на небольших примерах.
person Moti Korets    schedule 05.05.2018