Javascript 从JS中的ID自动创建变量?

Javascript 从JS中的ID自动创建变量?,javascript,Javascript,就在今天,经过几年的javascript编程之后,我遇到了一件让我大吃一惊的事情。浏览器为每个具有id的元素创建对象。对象的名称将与id匹配 因此,如果你有: <div id ="box"></div> 不首先为该变量赋值 出于某种原因,这似乎是即使它可以中断代码。有一个方法可以结束这种行为,但我现在更感兴趣的是摆脱它 你们知道有没有办法禁用它(也许)?我是不是太重视这件事了?因为这看起来确实是个坏主意。(这是IE介绍给你的提示) 更新:似乎FF只在“怪癖”模式下执行此

就在今天,经过几年的javascript编程之后,我遇到了一件让我大吃一惊的事情。浏览器为每个具有id的元素创建对象。对象的名称将与id匹配

因此,如果你有:

<div id ="box"></div>
不首先为该变量赋值

出于某种原因,这似乎是即使它可以中断代码。有一个方法可以结束这种行为,但我现在更感兴趣的是摆脱它

你们知道有没有办法禁用它(也许)?我是不是太重视这件事了?因为这看起来确实是个坏主意。(这是IE介绍给你的提示)


更新:似乎FF只在“怪癖”模式下执行此操作。其他浏览器,如IE6+和Chrome,可以立即使用。

是的,大多数浏览器都可以使用,但正如你所说的,有些浏览器(firefox)不能使用,所以不要指望它。在js中覆盖这些变量也很容易,我可以想象像
container
这样的东西可能会被使用该变量而不首先声明的人直接覆盖

没有办法在chrome afaik中实现这一点,但即使如此,要解决这一问题并为所有浏览器修复它也可能是一件麻烦事

不要把它看得太重要,但要小心。这就是为什么要回避变量的全局范围的原因之一

为了完整起见,默认情况下,这些浏览器都会这样做:Chrome、IE9&compat、Opera


更新:ECMAScript的未来版本可能包含某种选项,因为“是”的讨论正在进行,但这不会解决旧浏览器中的“问题”。

我认为这没什么大不了的。这看起来很混乱,特别是对于我们这些想到全局名称空间污染和冲突的人来说,但实际上它并没有真正引起问题

如果您声明自己的全局变量,它将覆盖浏览器为您创建的任何内容,因此实际上不会有任何冲突。我所能看到的唯一可能导致问题的地方是,如果您正在测试是否存在全局声明,以及基于对象ID的“自动”全局是否妨碍了这一点,并使您感到困惑


在实践中,我从未发现这是一个问题。但是,我同意这似乎是他们应该扔掉或允许你关掉的东西。

我认为没有办法禁用它,但你不需要太重视它。如果您害怕不可预知的bug,可以使用或来避免它们。它们将帮助你避免犯错误。例如,如果您使用未声明的变量,它们将警告您。

这里的问题是全局作用域在运行时由浏览器在其中定义了对象,您希望防止这些定义干扰您的代码。我不知道如何关闭这种行为,但我有两种解决方法:

1) 正如您链接到的文章中所建议的,您可以通过确保在使用每个变量之前定义它来解决这个问题。我将通过运行我的代码来实现这一点,这会警告这类事情(除了一系列其他常见错误)


2) 然而,由于可能会忘记通过JSLint运行代码,因此您可能更喜欢工具链中不能忘记的步骤。在这种情况下,请看一看-这是一个非常类似于javascript的语言,在使用之前编译成javascript,它将为您插入正确的
var
定义。事实上,我怀疑您无法编写依赖于使用CoffeeScript自动创建元素变量的代码。

这就是我能够想出的方法来删除为具有ID值的DOM对象自动创建的全局变量:

function clearElementGlobals() {
    function clearItem(iden, item) {
        if (iden && window[iden] && (window[iden] === item)) {
            window[iden] = undefined;
        }
    }

    var list = document.getElementsByTagName("*");
    for (var i = 0, len = list.length; i < len; i++) {
        var item = list[i];
        clearItem(item.id, item);
        clearItem(item.name, item);
    }
}
函数clearElementGlobals(){ 功能clearItem(iden,item){ if(iden和窗口[iden]&&(窗口[iden]==项目)){ 窗口[iden]=未定义; } } var list=document.getElementsByTagName(“*”); for(变量i=0,len=list.length;i 这将获取页面中所有对象的列表。它循环查找具有id值的对象,当有id值且存在全局变量且该全局变量指向该DOM对象时,该全局变量被设置为未定义。事实证明,浏览器对某些类型的带有名称属性的标记(如表单元素)也会执行相同的自动全局操作,所以我们也会清除这些标记

当然,这段代码不知道您自己的代码是否生成了与id同名的全局变量,因此显然最好不要在您自己的代码中这样做,或者在初始化全局变量之前调用此函数

不幸的是,您无法删除javascript中的全局变量,因此将其设置为未定义是最好的选择

仅供参考,我尝试了另一种方法,即枚举全局变量,查找作为HtmleElement实例且名称与其指向的元素id匹配的变量,但我找不到可靠的方法来枚举全局变量。在Chrome中,即使可以通过window对象访问它们,也不能在window对象上枚举它们。因此,我不得不反过来,获取所有具有id的DOM对象,并寻找与之匹配的全局对象

仅供参考,您在问题中询问了严格模式。严格模式仅适用于给定的代码范围,因此不会有任何方式使其影响全局命名空间的设置方式。要影响类似的内容,它必须是文档级别的内容,然后才能解析文档,比如DOCTYPE选项或类似的内容

此函数的注意事项

  • 在创建任何自己的全局或全局文件之前运行它
    function clearElementGlobals() {
        function clearItem(iden, item) {
            if (iden && window[iden] && (window[iden] === item)) {
                window[iden] = undefined;
            }
        }
    
        var list = document.getElementsByTagName("*");
        for (var i = 0, len = list.length; i < len; i++) {
            var item = list[i];
            clearItem(item.id, item);
            clearItem(item.name, item);
        }
    }