我在一个项目中使用Require.js。如果要定义一个模块,变量define
将被添加到全局命名空间中。
最近,我有一个变量名冲突,但奇怪的是,仅在Safari中,因为有一个带有ID为define
的HTML5规范标记,并且根据HTML5规范
窗口接口支持命名属性。支持的属性名称在任何时候都包括以下内容:
我认为用每个具有ID的HTML元素污染JS全局命名空间是个糟糕的主意,但我的观点不足以改变浏览器的行为方式。
在我的特定例子中,我找到了将包装这个答案的Require.js;但从更一般的意义上说:是否有一种方法可以防止规范中的这种细节?是否有防止这种GNS污染的技术(没有明显的答案:“不要使用ID”)?这种冲突至少可以通过JS控制台对开发人员(可能不是我)说清楚吗?
发布于 2014-01-26 13:03:45
HTML5的这种行为对RequireJS本身没有影响。我在Firefox和Chrome中运行了下面的代码。正如预期的那样,全局空间中的define
符号是RequireJS的定义函数。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
</head>
<body>
<p id="define">Paragraph.</p>
<button id="redefine">Redefine</button>
<script type="text/javascript">
console.log("before requirejs:", typeof window.define);
</script>
<script type="text/javascript" src="js/require.js"></script>
<script>
require.config({
baseUrl: "./js",
paths: {
jquery: 'jquery-1.10.2'
},
});
console.log("requirejs loaded:", typeof window.define);
require(["jquery"], function ($) {
$("#redefine").click(function () {
$("#define").replaceWith("<p id='define'>New paragraph.</p>");
console.log("redefined:", typeof window.define);
require(["foo"], function (foo) {
console.log(foo);
});
});
});
</script>
</body>
</html>
我使用typeof
来避免获得整个函数源的转储。这对我们的目的来说已经足够了。“重新定义”按钮是模拟DOM树的更改,人们可能认为它会覆盖window.define
的值。(模块foo
是一个只返回值"foo"
的琐碎模块。)单击处理程序中的require
显示RequireJS仍然有效。使用上面的代码,控制台的输出显示:
window.define
是DOM元素,RequireJS也会将define
重新定义为自己的值。define
,对DOM树的更改就不会改变它。因此,RequireJS不需要受到保护。
但是,坚持使用window.define
来访问id为"define“的元素的代码又如何呢?这类代码有缺陷,应予以修正。因此,问题很好地解决了这个问题。即使RequireJS是为了避免接触全局define
,依赖于window.define
作为DOM元素的代码仍然很脆弱。
是否有防止这种GNS污染的技术(没有明显的答案:“不要使用ID”)?
除了显而易见的答案之外,没有。(我认为“使用其他东西而不是I”等同于“不要使用I”)。
这种冲突至少可以通过JS控制台对开发人员(可能不是我)说清楚吗?
JS虚拟机可能会检测到冲突,但我不知道有任何这样的冲突。
那Safari呢?
这是Safari如何在JavaScript中处理全局变量方面的一个缺陷。没有其他浏览器的行为,如Safari。
这个储存库包含一组说明问题的文件。如果在Safari中加载,index.html
文件将显示控制台上出现故障。它在Firefox、Chrome、IE和Opera中加载良好。test.html
文件指出了问题所在。除了Safari之外,所有浏览器都将JavaScript中的变量声明(如顶层作用域的var foo
)视为隐藏由于具有id
属性集的元素而创建的任何同名变量。在除Safari之外的任何浏览器中,输出start of redefine:
的start of redefine:
将显示变量值的undefined undefined
。在Safari中,它显示了p#define p#define
。
已归档与RequireJS的一个问题,以建议一个改变,以解决这一情况。
如果建议的更改没有通过,那么解决方法是在加载define = undefined
之前执行RequireJS。没有必要做更多的事了。
https://stackoverflow.com/questions/21362298
复制相似问题