javascript internet-explorer scope browser-bugs

javascript - ¿Por qué IE nuke window.ABC variables?



internet-explorer scope (3)

El problema principal se puede ver aquí http://jsfiddle.net/Raynos/UxrVQ/ Todavía tengo que averiguar por qué IE sobrescribe window.hiya sin verificar.

[Editar]

De la especificación Página 38:

Para cada VariableDeclaration o VariableDeclarationNoIn en el código, cree una propiedad del objeto variable cuyo nombre es el identificador en VariableDeclaration o VariableDeclarationNoIn, cuyo valor no está definido y cuyos atributos están determinados por el tipo de código. Si ya hay una propiedad del objeto variable con el nombre de una variable declarada, el valor de la propiedad y sus atributos no se modifican.

Una posible explicación podría ser que, en el ámbito global, IE distingue entre el objeto window y el variable object para el alcance global al declarar variables. Alternativamente, establecer una propiedad en el objeto de window directamente podría no establecer la misma propiedad en el objeto variable . Si puede encontrar una especificación formal de JScript o tiene la fuente de IE por ahí, entonces podemos descubrir exactamente cuál es la peculiaridad.

[/Editar]

Gracias a @TimDown & @JuanMendes señalando eso es un problema con si escribir una propiedad en el objeto ventana es una declaración de variable.

La cuestión:

la declaración de variable se mueve a la parte superior del bloque. Incluso si el código está muerto. En IE, por alguna razón, declarará hiya como una variable local aunque clasifique con la propiedad del mismo nombre almacenada en la ventana.

Explicación:

Lo que está sucediendo es que tu declaras una variable llamada hiya. La instrucción var se elimina automáticamente a la parte superior del bloque. Una instrucción if no es un bloque, una función es. Así que si el código nunca se ejecuta en el bloque, la variable aún se declara.

En firefox reconocerá esa ventana .hiya es una declaración de hiya.

En IE, la declaración en el segundo script lo sobrescribe

Lo que está haciendo actaully

En 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(...)

En 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(...)

La solución es simplemente el espacio de nombres. Está utilizando el mismo nombre en dos lugares y accediendo a él en dos nombres diferentes. Use nombres diferentes o use cierres para dar alcance local.

Al ejecutar el siguiente bloque de código, FF y Chrome emiten typeof(hiya) = string mientras que IE7 / 8 typeof(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>

Cada uno de los siguientes hace que el problema desaparezca:

  • Combinando todo en un solo bloque <script> .
  • Quitando el bloque if .
  • Renombrando var hiya = 1 a var hiya2 = 1 .
  • Renombrando var hiya = 1 a window.hiya = 1 .
  • Renombrando var hiya = 1 a hiya = 1 .

¿Que esta pasando? ¿Hay un error de alcance en IE?


IE es tonto, no reconoce que window.varName y var varName acceden a la misma variable en algunos casos.

Cuando se encuentra una nueva etiqueta de script, primero inicializa todas las variables declaradas con var. No ejecuta la declaración var (la parte que lo inicializaría a "hiya"). Simplemente lo inicializa a indefinido. No hará eso si previamente fue declarado con var.

Si su código estaba en una sola etiqueta de script, este error no ocurriría. Además, si la primera declaración de hiya se hizo con var, este error tampoco ocurriría.

Específicamente, en su segunda etiqueta de script, IE primero busca las declaraciones var, encuentra una var var hiya = 1 ; Luego dice, hiya no se ha inicializado con una sentencia var previamente (IE es tonto, otros navegadores reconocen que window.hiya hace lo mismo) e inicializa hiya, sobrescribiendo window.hiya antes de ejecutar cualquier código.

Soluciones posibles:

  • Mantenga su código dentro de la misma etiqueta de secuencia de comandos
  • No inicializar variables con window.hiYa
  • Si no controla uno de los scripts, asegúrese de que el script que usa var sea el primero

Última nota para aclarar qué hacen los analizadores de JS a tu código. Cuando el analizador JS ve su código, lo transforma en lo siguiente:

<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>

Entonces, si pone todo en una etiqueta de script, este es el código (después de que el motor JS movió las declaraciones var a la parte superior), para que pueda ver que no hay forma de que el IE pueda estropearlo, ya que su window.hiya asignación de window.hiya sería después de la var que se movió a la parte superior.

<html> <body> <script type="text/javascript"> var hiya; window.hiya = ''hiya''; if( false ) { hiya = 1; } document.write( "typeof(hiya) = "+ typeof(hiya) ); </script> </body> </html>


Lo que encontraste se debe a:

  1. var es una afirmación
  2. No hay alcance de bloque en JS
  3. Las declaraciones se ejecutan antes de que se ejecute el código

Entonces, lo que sucede es que JavaScript ejecutará la instrucción var antes que cualquier otra cosa, pero no evaluará la expresión de asignación, por lo que hiya tendrá el valor predeterminado de undefined .

Como Raynos ya indicó, IE ejecutará cada uno de los scripts por sí mismo, por lo tanto, el comportamiento descrito anteriormente hará que los resultados no estén definidos.