2011-07-28 103 views
4

我觉得很方便地设置一个变量具有相同的名称为元素的ID,例如:我可以使用ID作为变量名吗?

randomDiv = document.getElementById("randomDiv"); 
    randomDiv.onclick = function(){ /* Whatever; */ } 
    randomDiv.property = "value"; 

这个工作在Chrome和Firefox,但不是IE8;给出错误对象不支持此属性或方法

是否正在创建一个名称与元素ID错误(或错误操作)匹配的变量,或者这是Internet Explorer另一个实例的动作?

+1

它在IE中工作,如果你'var randomDiv = document.getElementById(“randomDiv);'? –

+0

我不明白为什么这不起作用 –

回答

6

使全局变量自动被认为是不好的做法,因为它可以是很难说,看在某些代码中,无论是故意还是忘记在某处声明变量。自动创建像doesn’t work in ES5 strict mode这样的全局变量,并可能在未来版本的ECMAScript中逐步淘汰。

在浏览器的JavaScript 的全球范围实际上是window。当你参考document时,你会得到window.document。在浏览器中创建全局变量的最佳做法是将其添加到window(Node.js中的global)。这里的an example from jQuery

window.jQuery = window.$ = jQuery; 

window一些特性(因此一些全局变量)是只读的,你不能覆盖他们。 window.document是一个(在Chrome中进行测试,这是所有浏览器特定的和可以改变):

window.document; // → Document 
window.document = 'foo'; // → "foo" // It worked! 
window.document; // → Document // Hmm, no it didn’t 

事实证明,大多数浏览器创建的文档中的每个ID上window(因此全局变量)属性。许多浏览器不会让它们成为只读文件,您可以用自己的文件覆盖它们,但Internet Explorer会覆盖它们。

这是JavaScript中的全局变量可能很危险的另一个原因 - 您的一个ID可以匹配只读的window属性(今天或某些未来的浏览器)。

在顶层(不在函数内部),var声明全局变量。在顶层陈述var document = 'foo'不会抛出错误,但document仍然是Document,而不是"foo"

顺便说一句,新的上下的浏览器(支持ES5),让您与Object.defineProperty创建自己的只读全局:

Object.defineProperty(window, 'foo', { value: 'bar', writable: false }); 
foo = 'baz'; 
foo; // → "bar" 

我有三个选项供你。

  1. 继续使用你的元素全局变量,但让他们独立,如果他们已经存在(上window创建它们明确地这样的代码是清晰和冷静与ES5):

    if (! window.randomDiv) { 
        window.randomDiv = document.getElementById('randomDiv'); 
    } 
    
  2. 创建一个对象,在window上,用作应用程序自己的名称空间,不会干扰其他库或浏览器。这是常见的,并认为相当不错的做法,尤其是如果它需要跨JavaScript文件被访问:

    // Early in your code… 
    window.Fantabulum = {}; 
    // Later on… 
    Fantabulum.randomDiv = document.getElementById("randomDiv"); 
    
  3. 避免让全局。请确保您的应用程序的代码是一个函数内(应该已经让你的其他变量不是全局性的,不具有相同的限制!),并为您的元素声明变量:

    (function(){ 
        var randomDiv = document.getElementById("randomDiv"); 
    })(); 
    
+1

对建议#3的一个小小的评论:代码与您的代码完全相同将导致大多数浏览器的语法错误,因为它会[作为函数**语句**解析](http://stackoverflow.com/a/ 17332932/507784),而不是函数**表达式**,函数语句不能跟在'()'后面。解决方法是用圆括号包围'function(){/ * ... * /}'代码,强制它被解析为一个函数表达式,即'(function(){/ * ... * /}( ))'或'(function(){/ * ... * /})()'。或将其分配给一个变量。 – GregL

+0

@GregL很好抓,固定。 – s4y

1

randomDiv不是已定义/已知的“全局范围变量”。

Declaring global variable

+0

好吧,也许把它叫做全局变量是一个误称,但问题是为什么can not variableName === id?虽然很好,但感谢您的输入 – Gary

+1

Hi Fantabulum,你指的是variableName,是JavaScript的一部分,而id是DOM,它们是分开的东西 –

+0

你是绝对的[R ight,那么为什么错误? – Gary

2

这是IE的一个怪癖具有相同的名称作为元素ID和名称创建全局变量。你可以用同样的名字创建一个全局的,但是有一些怪癖。

这是一个非常可怕的想法。如果你不喜欢打字的document.getElementById,只是做一个小包装函数它如:

funciton get(id) { 
    return typeof id == 'string'? document.getElementById(id) : id; 
} 
+0

我同意像这样创建全局变量是JavaScript的一个危险特性,但将元素存储在变量中而不是每次调用getElementById都是非常好的做法。 – s4y

+0

这是一个非常漂亮的功能。我不介意打字,我只是认为它使用变量名称比尝试重新引用元素更清晰;特别是当我使用它。我可以考虑其他一些例子,但我认为它们不值得一提。你是否每次都使用document.getWarning或者你有更好的方法? – Gary

+0

@Sidnicious - 非常满意存储引用,只是不会为每个具有id的元素创建全局变量。 – RobG

相关问题