Доступ к глобальному объекту при использовании requirejs

Я знаю, что не рекомендуется использовать глобальный объект, и вся идея использования AMD заключается в том, чтобы избежать использования глобального объекта. Но для некоторого устаревшего кода я должен определить некоторые вещи в глобальном объекте. В настоящее время код выглядит следующим образом:

//example2.js
define(function(){
  var globalObject = window;
  globalObject.x = ...
  globalObject.y = ...
});

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

//example1.js
x = ...
y = ...

Я знаю, я знаю, что вы ненавидите этот код, но давайте быть в курсе: как можно получить глобальную переменную структурированным образом внутри функции define() в requirejs? Мне жаль, что функция, которая передается в define(), есть что-то вроде скрытого последнего параметра:

//example3.js
define(function(globalObject){
  globalObject.x = ...
  globalObject.y = ...
});

Или даже проще: переменная this будет указывать на глобальный объект внутри этой функции. Например:

//example4.js
define(function(){
  this.x = ...
  this.y = ...
});

Примечание: Я не уверен в этом последнем. Расследование переменной this внутри функции, переданной в require(), говорит о том, что она равна window, что может быть ответом на мой вопрос, но я не смог найти документацию, в которой упоминается контекст, который выполняется переданная функция. Может быть, он работает в контексте глобальной переменной?

Ответ 1

Если вы не находитесь в строгом режиме, вы можете сделать это:

(function() {
  var global = this;

  define(function(){
    global.x = ...
    global.y = ...
  });
})();

Внешняя анонимная функция, которую мы немедленно вызываем, вызывается без особого специального значения this, и поэтому (поскольку это не в строгом режиме), глобальный объект получает this. (В строгом режиме вместо этого он получит undefined.) Таким образом, мы захватываем this в переменную (global) внутри анонимной функции и используем ее из функции, которую вы передаете в define (которая закрывается над ней).

Ответ 2

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

window.js

define(function(){
   return window;
});

app.js

define(['window'], function(win) {
  // Manipulate window properties
  win.foo = 1;  
  console.log(win.foo);      
});

Ответ 3

Вариант ответа @TJCrowder, который также работает в строгом режиме:

(function(global) {
    define(function() {

        global.a="this";
        global.b="that";

    });
})(this);

Вызвав сразу вызываемую функцию с аргументом 'this' (который вне функции является глобальной областью), то чем бы ни была глобальная область, она передается в IIF как аргумент global.

Это также позволяет избежать жесткого кодирования объекта "window", что является преимуществом, поскольку оно не применяется в нерабочих средах.