就在今天经过几年的javascript编程后,我遇到了令我吃惊的东西。浏览器为每个具有id的元素创建对象。对象的名称将与id匹配。
所以如果你有:
<div id ="box"></div>
你可以这样做:
alert(box); //[object HTMLDivElement]
首先不为该变量分配任何内容。 See the demo
出于某种原因,这似乎是in the standards,即使它可能会破坏some cases中的代码。有open bug来结束这种行为,但我现在更感兴趣摆脱它。
你们知道是否有办法禁用此功能(strict mode可能)?我是否过分重视?因为这看起来确实是一个坏主意。 (它是由IE引入给你一个提示)。
更新:似乎FF只在怪癖模式下执行此操作。其他浏览器,如IE6 +和Chrome,就可以随时使用。
答案 0 :(得分:10)
ECMAScript 5 strict应该为您cannot use undeclared variables提供帮助。我不确定哪些浏览器目前支持严格模式,但我知道Firefox 4可以。
您链接的HTML规范提及a proposal to reduce pollution of the global scope by limiting this behavior to quirks-only。
我不知道这个功能是否在原始规范中,但我确实希望在后续版本的ECMAScript中将其删除,禁止或以其他方式无效。 ES6将基于ES5严格。
JavaScript有许多功能,使初学者和初学者更容易使用,我怀疑这是一个这样的功能。如果您是专业人士并希望使用质量代码,请使用"use strict";
并始终JSLint使用您的代码。 如果您使用这些指南,则功能不应该打扰您。
这是a useful video about ES5 YUI Theatre的礼貌(虽然它已经有2年了,但目前仍然没有相关的ES6)。
答案 1 :(得分:6)
我认为这不是什么大问题。对我们这些考虑全球命名空间污染和冲突的人来说,这似乎很麻烦,但在实践中它并没有真正引起问题。
如果您声明自己的全局变量,它将覆盖浏览器为您创建的任何内容,因此实际上没有任何冲突。唯一可以看到它可能导致问题的地方是,如果您正在测试是否存在全局声明,并且基于对象ID而导致的“自动”全局,并且会让您感到困惑。
在实践中,我从未见过这是一个问题。但是,我同意它似乎应该摆脱或允许你关闭。
答案 2 :(得分:3)
是的,大多数浏览器会这样做,但是再次像你说的那样(firefox),所以不要指望它。在js中覆盖这些变量也很容易,我可以想象container
之类的东西可能会被使用该变量的人覆盖,而不会先声明它。
没有办法在chrome afaik中解决这个问题,但即使这样,想出这个并为所有浏览器修复它也可能是一件麻烦事。
不要过于重视,但要注意它。这就是为什么要逃避变量的全局范围的原因之一。
为了完成,这些浏览器默认情况下默认执行:Chrome,IE9&amp; compat,Opera
更新:ECMAScript的未来版本可能包含某种选项,因为是讨论正在进行,但这不会解决旧浏览器中的“问题”。
答案 3 :(得分:2)
答案 4 :(得分:2)
这里的问题是全局范围在浏览器运行时在其中定义了对象,并且您希望防止这些定义干扰您的代码。我不知道如何关闭这种行为,但我确实有两种解决方法:
1)正如您链接的文章所述,您可以通过确保在使用之前定义每个变量来解决此问题。我会通过JSLint运行我的代码来实现这一点,CoffeeScript会警告这类事情(除了一堆其他常见错误之外)。
2)但是,由于可能忘记通过JSLint运行代码,您可能更喜欢工具链中的一个您不能忘记的步骤。在这种情况下,请查看{{3}} - 它是一个非常类似于javascript的语言,您在使用前编译为javascript,它将为您插入正确的var
定义。事实上,我怀疑你不能编写依赖于使用CoffeeScript创建自动元素变量的代码。
答案 5 :(得分:0)
这是我能够想出的用于移除为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);
}
}
这将获取页面中所有对象的列表。它循环查找具有id值的值,当存在id值并且存在全局变量且该全局变量指向该DOM对象时,该全局变量设置为undefined。事实证明,对于某些类型的带有name属性的标签(如表单元素),浏览器也会执行相同的自动全局操作,因此我们也清除了这些。
当然,这段代码无法知道您自己的代码是否创建了一个与id同名的全局变量,所以显然最好不要在自己的代码中执行此操作,或者在全局变量之前调用此函数已初始化。
不幸的是,你无法在javascript中删除全局变量,因此将其设置为undefined是最好的。
仅供参考,我尝试以另一种方式执行此操作,您枚举全局变量,查找作为HTMLElement实例的变量,并且其名称与其指向的元素的id相匹配,但我找不到枚举全局变量的可靠方法。在Chrome中,即使您可以通过窗口对象访问它们,也无法在窗口对象上枚举它们。因此,我必须通过获取具有id的所有DOM对象并寻找与它们匹配的全局变量来反过来。
仅供参考,您在问题中询问过严格模式。严格模式仅适用于给定的代码范围,因此不会有任何方法导致它影响全局命名空间的设置方式。为了影响这样的事情,在解析文档之前,它必须是文档级别的东西,如DOCTYPE选项或类似的东西。
具有此功能的警告。