Javascript 为什么IE使用nuke window.ABC变量?
当运行以下代码块时,FF和Chrome输出Javascript 为什么IE使用nuke window.ABC变量?,javascript,internet-explorer,scope,browser-bugs,Javascript,Internet Explorer,Scope,Browser Bugs,当运行以下代码块时,FF和Chrome输出typeof(hiya)=string,而IE7/8输出typeof(hiya)=未定义 <html> <body> <script type="text/javascript"> window.hiya = 'hiya'; </script> <script type="text/javascript">
typeof(hiya)=string
,而IE7/8输出typeof(hiya)=未定义
<html>
<body>
<script type="text/javascript">
window.hiya = 'hiya';
</script>
<script type="text/javascript">
if( false ) {
var hiya = 1;
}
document.write( "typeof(hiya) = "+ typeof(hiya) );
</script>
</body>
</html>
window.hiya='hiya';
if(false){
var hiya=1;
}
文件。书写(“typeof(hiya)=“+typeof(hiya));
以下每一项都会使问题消失:
- 将所有内容合并到一个
块中 - 删除
块if
- 将
重命名为var hiya2=1
var hiya2=1
- 将
重命名为var hiya=1
window.hiya=1
- 将
重命名为var hiya=1
hiya=1
发生了什么?IE中是否存在范围缺陷?核心问题可以在这里看到,我还没有找到IE未经检查就覆盖window.hiya的原因 [编辑] 从规范中删除。第38页: 对于每个变量声明或 代码中的VariableDeclarationNoIn, 创建变量的属性 对象,其名称是中的标识符 变量声明或 VariableDeclarationNoIn,其值为 未定义,且其属性为 由代码类型决定。如果 已存在的属性 名为 声明的变量的值 属性及其属性不可用 变了 一种可能的解释是,在全局范围内,IE在声明变量时区分了全局范围的
窗口
对象和变量对象
。或者,直接在窗口
对象上设置属性可能不会在变量
对象上设置相同的属性。如果你能找到一个正式的JScript规范,或者有IE的来源,那么我们就可以确切地找出其中的怪癖
[/Edit]
感谢@TimDown&@JuanMendes指出,将属性写入窗口对象是否是变量声明是一个问题
问题:
变量声明被移动到块的顶部。即使代码死了。在IE中,由于某种原因,它会将hiya声明为局部变量,即使它使用存储在window上的同名属性初始化
说明:
现在发生的是,您声明了一个名为hiya的变量。var语句会自动删除到块的顶部。if语句不是块,函数是块。因此,如果代码从未在块中运行,变量仍然会被声明
在firefox中,它将识别window.hiya是hiya的声明
在IE中,第二个脚本中的声明覆盖了它
它实际上在做什么
在firefox中:
// script block 1
var hiya; // window.hiya counts as a declaration
window.hiya = "hiya"; // set
// script block 2
if (false) hiya = 1;
document.write(...)
在IE中:
// script block 1
window.hiya = "hiya";
// script block 2
var hiya; // redeclared here because window.hiya "isn't" a declaration
if (false) hiya = 1;
document.write(...)
解决方案只是名称空间。您在两个地方使用相同的名称,并使用两个不同的名称访问它。使用不同的名称或使用闭包来提供本地范围。您遇到的问题是由于:
var
是一个语句var
语句,然后再执行其他语句,但它不会计算赋值表达式,因此hiya
将默认为undefined
的值
<html>
<body>
<script type="text/javascript">
window.hiya = 'hiya';
</script>
<script type="text/javascript">
if( false ) {
var hiya = 1;
}
document.write( "typeof(hiya) = "+ typeof(hiya) );
</script>
</body>
</html>
正如Raynos已经声明的那样,IE将自己执行每个脚本,因此上述行为将导致
hiya
未定义。IE是哑的,在某些情况下,它无法识别window.varName
和var varName
访问相同的变量
当遇到新的脚本标记时,它首先初始化使用var声明的所有变量。它不运行var语句(将其初始化为“hiya”的部分)。它只是将其初始化为未定义。但是,如果它以前是用var声明的,它就不会这样做
如果代码位于单个脚本标记中,则不会发生此错误。此外,如果hiya的第一次声明是使用var完成的,那么也不会发生此错误
具体来说,在第二个脚本标记中,即首先查找var语句,它会找到varvar hiya=1
;然后它说,hiya以前没有用var语句初始化过(也就是说,如果是哑的,其他浏览器会识别window.hiya做同样的事情),并初始化hiya,在执行任何代码之前覆盖window.hiya
可能的解决办法:
- 将代码保持在同一个脚本标记内
- 不要使用window.hiYa初始化变量
- 如果您不能控制其中一个脚本,请确保首先使用var的脚本
<html>
<body>
<script type="text/javascript">
window.hiya = 'hiya';
</script>
<script type="text/javascript">
// IE is dumb, it doesn't recognize that hiya is already
// defined as window.hiya, so it's initialized to undefined here
var hiya;
if( false ) {
hiya = 1;
}
document.write( "typeof(hiya) = "+ typeof(hiya) );
</script>
</body>
</html>
一开始就不要写这么棘手的东西怎么样哈。我遇到的现实问题要复杂得多,如果没有加载另一个库,则会有一个条件来定义某些内容。这是我可以解决的问题,但我真的很想知道为什么会发生这种情况。@delnan:Snarky,嗯?我认为很明显,这不是真正的代码,这只是一个减少,显示了问题。就像所有操作人员在发布问题之前应该做的一样,我在Ext.ns中遇到了同样的问题,它使用window从字符串创建名称空间。。在其他地方,在googleclosure生成的一些模板代码中,它还试图创建到相同的名称空间(cci.templates)中,并覆盖了原始的cci名称空间对象,因为它在全局范围中使用了一个var来生成名称空间对象。起初我很困惑,因为它会测试
如果(!wi