首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >警惕JS全局命名空间中的HTML in

警惕JS全局命名空间中的HTML in
EN

Stack Overflow用户
提问于 2014-01-26 10:29:51
回答 1查看 453关注 0票数 3

我在一个项目中使用Require.js。如果要定义一个模块,变量define将被添加到全局命名空间中。

最近,我有一个变量名冲突,但奇怪的是,仅在Safari中,因为有一个带有ID为defineHTML5规范标记,并且根据HTML5规范

窗口接口支持命名属性。支持的属性名称在任何时候都包括以下内容:

  • 活动文档中任何HTML元素的id内容属性的值,具有非空的id内容属性.

我认为用每个具有ID的HTML元素污染JS全局命名空间是个糟糕的主意,但我的观点不足以改变浏览器的行为方式。

在我的特定例子中,我找到了将包装这个答案的Require.js;但从更一般的意义上说:是否有一种方法可以防止规范中的这种细节?是否有防止这种GNS污染的技术(没有明显的答案:“不要使用ID”)?这种冲突至少可以通过JS控制台对开发人员(可能不是我)说清楚吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-26 13:03:45

HTML5的这种行为对RequireJS本身没有影响。我在Firefox和Chrome中运行了下面的代码。正如预期的那样,全局空间中的define符号是RequireJS的定义函数。

代码语言:javascript
运行
复制
<!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仍然有效。使用上面的代码,控制台的输出显示:

  1. 即使最初window.define是DOM元素,RequireJS也会将define重新定义为自己的值。
  2. 一旦RequireJS定义了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。没有必要做更多的事了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21362298

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档