【问题标题】:Dojo 1.8 - create global variable in requireDojo 1.8 - 在 require 中创建全局变量
【发布时间】:2012-10-30 17:00:57
【问题描述】:

我注意到在我的团队升级到 Dojo 1.8 后,我正在为一个项目处理的一些旧脚本不再工作。具体来说,他们创建的全局变量不再被创建。

我挖掘了一下,发现 Dojo 1.8 团队非常反对全局变量。如此反对,事实上,它们使用户在物理上不可能在所需脚本中使用以下代码在其要求末尾创建全局变量:

req.eval =
        function(text, hint){
            return eval_(text + "\r\n////@ sourceURL=" + hint);
        };
var eval_ = new Function('return eval(arguments[0]);');

这太棒了,但是我正在使用的旧代码无法更改,所以我一直在尝试找出如何解决这个问题并改为在本地上下文中执行 eval。

幸运的是,旧版本的 Dojo 中仍然存在 dojo.eval,这正是我想要的。所以我只需要访问req.eval 并将函数更改为return dojo.eval(...) 或在某些情况下甚至只是eval(...)

问题是,我无法弄清楚如何访问req。以下是发生的事情:

我在 HTML 文件顶部的脚本标记中包含 dojo.js。它加载到自己的脚本文件中。

dojo.require 可以从我自己的文件中访问。它在脚本文件中用define 定义:

'dojo/_base/loader':function(){
define(["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) {

我不确定这是否重要。无论如何,在dojo.require 的范围内,我可以看到名为injectModule 的东西,而在我自己的文件中却看不到。 injectModule 是一个局部变量,所以你不能用this 看到它。它在文件开头的匿名函数中定义,即

(function(){ ... injectModule = function(){} ... })();

injectModule 函数中,有以下行:

req.getText(url, legacyMode!=sync, xhrCallback);

转到req.eval。所以injectModule 可以看到req

我不知道该怎么办。我的邪恶 JavaScript 技巧都没有帮助我开始导航这个范围的僵局。一个好的开始是弄清楚如何从调用dojo.require 的外部脚本文件中查看injectModule。不过,我无法使用“绑定”来做到这一点,因为它是在匿名函数中定义的局部变量。这甚至可能吗?

为了让事情变得更简单,这里有一个摘要:

文件 1:

<script src="dojo.js"></script>
dojo.require(File 3);
console.log(globalVar);

文件 2:

(function(){req.eval = unhelpful function})();
define(["require"], function(module){
    dojo.require = function(x){req.eval(x)}
});

文件 3:

globalVar = ...;

我可以修改文件 1 和 3,但文件 3 总是需要一个全局变量。我无法修改文件 2。目标是将文件 2 中的req.eval 更改为更好的功能。

提前声明全局变量不起作用,因为范围更改意味着文件 3 仍然无法看到它。

反射和字符串替换不起作用,因为范围错误并且JS在服务器端被缩小了。

覆盖文件 1 中的方法不起作用,因为我无法看穿范围。

使用 JavaScript bind 函数也没有结果。

【问题讨论】:

  • 你试过文件 3 中的window.globalVar = 42 吗?
  • 我没有,这行得通,谢谢。我真的不明白 n = 5window.n = 5 最终是如何不同的。

标签: javascript dojo scope


【解决方案1】:

为此,dojo 创建了dojo.global。它将指向已加载 dojo 的 window(非常适合框架布局)。

所以像这样声明你的全局变量:

require([ "dojo/_base/kernel", ... ] , function(kernel) {
    kernel.global.globalVariable = 1;
    console.log('set')
})

dojo.addOnLoad(function() {console.log('get', globalVariable);});

【讨论】:

  • 在 Dojo 1.8 中 global 现在在 dojo/_base/kernel 中,所以它是 kernel.global 而不是 dojo.global
【解决方案2】:

全局作用域可以通过全局window对象访问,所以window.foo = 'bar'与创建全局变量foo是一样的。更多细节在这里:https://stackoverflow.com/a/4862268/168382

【讨论】:

  • 这行得通,尽管我仍然不确定为什么。我原以为 n = 5window.n = 5 做了同样的事情,但我猜 Dojo 的做法让他们做不同的事情,第二个仍然有效。
  • 关于 Dojo 自己的 global 别名的另一个答案似乎更正确,因为它可以在 Node.js 等上下文中工作;此处的文档:dojotoolkit.org/reference-guide/1.8/dojo/_base/…
猜你喜欢
  • 1970-01-01
  • 2016-10-25
  • 2015-03-24
  • 2013-03-23
  • 1970-01-01
  • 2017-11-12
  • 1970-01-01
  • 2021-12-11
  • 2011-01-02
相关资源
最近更新 更多