使用requirejs时访问全局对象的方法

10

我知道不推荐使用全局对象,而使用AMD的整个理念是避免使用全局对象。但是对于一些旧代码,我必须在全局对象中定义一些内容。目前代码看起来像这样:

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

它可以工作但是硬编码全局对象 window 看起来不太好,我很想知道是否有可能将其删除。当没有使用 define() 时,代码看起来像这样:

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

我知道,我知道你讨厌这段代码,但让我们言归正传:如何以结构化的方式在 define() 函数内部访问全局变量?我希望在传递给 define() 的函数中有一个类似于隐藏的最后参数,像这样:

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

甚至更简单的是:在该函数内,this变量将指向全局对象。例如:

Or even simpler: the this variable would point to the global object inside that function. For example:


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

注意:我不确定最后一个问题。在调用require()时,研究传递给其的函数内部的this变量显示它等于window,这可能是我的问题的答案,但我尚未找到任何提及传递函数运行上下文的文档。也许它确实在全局变量的上下文中运行?

3个回答

15

我建议您创建一个返回window对象的模块。这对于单元测试(模拟依赖项)非常有用。

window.js

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

app.js

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

如果您实际上想要全局对象,例如您希望您的模块在其他上下文中运行,那又怎样呢? - gman
如果我理解你的意思正确,@gman...说我们的代码在iframe中,但我们需要顶部全局对象。我们可以这样做:// iframe内的代码 define(['window'], function(win) { var topWin = win.top; // 操作iframe的window属性 win.foo = 1; console.log(win.foo); // 操作顶部窗口属性 topWin.foo = 2; console.log(topWin.foo); }); - Túbal Martín
抱歉,我的意思是我没有在浏览器中运行,因此全局对象不是 window - gman
感谢这个,为了快速将先前的非-{AMD&equiv}代码中的naive全局变量转换为AMD,我怀疑这里的3个解决方案中,这个解决方案显然是最好的,因为它定义并使用一个全局MODULE来保存naive全局变量,特别是一个AMD https://en.wikipedia.org/wiki/Singleton_pattern用于“window”,以便{还允许其他甚至同时的全局空间插入,包括定期w/o编辑模块} + {esp作为单例r用于POST-AMD设计的全局变量(根据https://dev59.com/NG035IYBdhLWcg3wH8Ul的所有4个评级0+解决方案)},所以我现在尝试它来快速将大量旧代码转换为AMD,如果运行良好,则+1! - Destiny Architect
@gman 让它返回 self 而不是 window。 - jpaugh

5
@TJCrowder的答案有一种变化形式,它也适用于严格模式:
(function(global) {
    define(function() {

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

    });
})(this);

通过使用参数“this”调用立即调用的函数(在函数外部是全局范围),然后无论全局范围是什么,它都作为参数“global”传递给IIF。
这也避免了将代码硬编码到“window”对象上,这是一个优点,因为在非浏览器环境中不适用。

如果我将该代码放入文件并将其传递给Node,则无论我是否处于严格模式,this都为{} - Louis
@Louis 我相信 self 在 Node 中也可以使用,而且在浏览器中肯定可以使用。 - jpaugh

5
如果你没有启用严格模式,你可以这样做:
(function() {
  var global = this;

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

我们立即执行的外部匿名函数不带特定的this值进行调用,因此(由于这不是在严格模式下),将全局对象作为this进行调用。(在严格模式下,它将接收undefined)因此,我们将this存储在一个变量(global)中,在您传递给define的函数中使用它(该函数对其进行封闭)。


这是一个好主意,但我仍然想知道是否有一种机制可以从define()函数内部实现,而不需要将我的代码嵌入到立即调用函数中? - AlexStack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接