【问题标题】:Redeclared javascript global variable overrides old value in IE重新声明的 javascript 全局变量覆盖 IE 中的旧值
【发布时间】:2011-02-07 18:23:20
【问题描述】:

(在 cmets 之后创建一个单独的问题:Javascript redeclared global variable overrides old value

我正在使用方括号表示法创建一个全局范围的变量,并在外部 js 文件中为其分配一个值。

在另一个 js 文件中,我声明了一个与我刚刚在上面创建的同名的 var。注意我没有赋值。由于这是对同一变量的重新声明,因此不应按照此处所述覆盖旧值:http://www.w3schools.com/js/js_variables.asp

创建 2 个包含以下内容的 javascript 文件: 脚本1

//create global variable with square bracket notation
window['y'] = 'old';

脚本2

//redeclaration of the same variable
var y;

if (!y) y = 'new';

alert(y); //shows New instead of Old in IE

在你的 html 文件中包含这两个文件

<html>
 <head></head>
 <body>

  <script type="text/javascript" src="my.js"></script>
  <script type="text/javascript" src="my2.js"></script>

 </body>
</html>

在 Firefox 和 Chrome 中打开此页面会提示“旧”,这是预期的行为。但是在 IE 8 中,页面实际上会提示“新”

关于为什么会在 IE 上发生这种情况的任何想法?

【问题讨论】:

  • 如果将所有代码内联到 HTML 文件中会发生什么?它在 Firefox 3.5.8、Chrome 5.0.342.7 和 Konqueror 4.3.5 中为我提供了相同的结果(旧)。其他浏览器的结果会很有用。
  • 如果将所有代码放在一个文件中,会发生提升,问题可能不会出现。
  • 是的,如果您将所有代码放在一个位置,则警报会在所有浏览器上显示“旧”

标签: javascript internet-explorer internet-explorer-8 global-variables scope


【解决方案1】:

如果您希望 y 是全局的,您可以在第二个文件中完全删除 var y 行。

这背后的原因是,既然您希望 y 无论如何都是全局的,那么只需将其视为全局且已声明即可。 JavaScript 在没有 var 前缀的情况下使变量成为全局变量的副作用在这种情况下对你有利。在 IE8 中测试,效果很好。

编辑:至于为什么会发生这种情况,我将其归结为 IE 跨文件处理全局变量和声明提升的组合中的一个错误。但是,实际上,您应该只在一个地方声明任何变量,尤其是全局变量。遵循这个经验法则可以避免您的问题。

【讨论】:

  • 感谢您的建议。说得通。虽然知道为什么这在 IE 中不能正确运行仍然很有趣。
  • 令人惊讶的是,IE 的 JavaScript 实现似乎可能存在错误。
  • 是的,理想情况下我们只想在一个地方声明一个全局变量。我的用例是我有多个 js 文件,每个文件都使用这种模式声明一个命名空间类: Script1 : if (!a) a = {}; a.b = 函数() {....}; Script2 if (!a) a = {}; a.c = 函数() {....};现在这工作正常,直到第一个脚本使用 window.a 或 window['a'] 来声明 a 然后 IE 中断。由于多个页面可以选择包含哪些文件,因此每个页面都必须检查是否存在。
  • 我想的也差不多。这类似于dojo.declare。您可能想看看他们是如何做到的,或者甚至只是使用道场:api.dojotoolkit.org/jsdoc/1.3/dojo.declare
  • 有趣的是,这个错误出现了,因为我有我自己的自定义 dojo 小部件以及我自己的使用相同命名空间前缀的类。例如。 a.myDojoWidget(dojo 小部件)后跟 a.myClass(简单 js 类) 问题是 dojo.declare 以这种方式声明类:window['a'] = {},然后是 a['myDojoWidget'] = .. 我通过不做 var a 避免了这个问题(根据你的建议)。
【解决方案2】:

这发生在 IE 中,因为重新声明的行将 y 设置为未定义。然后,如果y 未设置,则行测试通过并且y 更改为“new”。

将第二个脚本改为:

//redeclaration of the same variable
var y;

alert(y); // is undefined in IE

if (!y) y = 'new';

alert(y); //shows New instead of Old in IE

【讨论】:

  • 对,我明白。但是,如果您要将 2 个文件的内容合并到一个位置,则 y 将不再是未定义的,并且重新声明不会将 y 设置为未定义。结果,警报将显示“旧”
  • 在 IE 中,所有声明都在代码的其他部分之前执行。在第二个包含中,如果您制作第一行 alert(window['y']) 您将看到该值未定义。如果您注释掉重新声明行,您将看到预期的“旧”出现。
  • 其实这种情况在所有浏览器中都会发生,叫做hoisting;但是,在这种情况下,IE 似乎做错了并导致覆盖。
【解决方案3】:

简化测试用例:

<script>
    window.foo= 1;
</script>
<script>
    var foo;
    alert(foo);
</script>

是的,这绝对是 IE 的 JScript 引擎中的一个错误。

为什么会这样?为什么 IE 会做它所做的任何疯狂的事情?发出烦躁的声音,继续前进,尽量避免这样做......

【讨论】:

  • 如果您将其范围缩小为“您有问题”和“IE 有问题”,请每次都使用 IE...
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 2019-08-21
  • 2015-03-13
  • 2014-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多