2009-09-12 17 views
7

Tengo una función de JavaScript que no se ejecutará y arrojó un error. Me tomó alrededor de una hora darme cuenta de que mi forma tenía el mismo nombre que la función. Parecía extraño que un nombre de formulario entrara en conflicto con un nombre de función, pero cambio el nombre de todos modos y todo funcionó bien. ¿Alguien sabe por qué esto pasaría?Función de Javascript y conflicto de nombre de formulario

Si ejecuta este código fallará, pero si cambia el nombre del formulario, funciona, muy extraño.

<html> 
<head> 
<title>Untitled Document</title> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
<script type="text/javascript"> 
function mytest(){alert("hello");} 
</script> 
</head> 
<body> 
<form name="mytest" ></form> 
<a href="#" onClick="mytest();">Click Me</a> 
</body> 
</html> 

Estoy ejecutando esto en IE6. Lo que me resulta extraño es que uno es un código Javascript y el otro es un atributo de HTML.

enlace en vivo donde se puede ver que esto ocurra:
JSBin

+0

Encontré este enlace que también lo explicaba http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html –

Respuesta

6

La función es un miembro en el objeto window, y la forma es un miembro de la colección forms en el objeto document. Cuando el script busca una coincidencia para el identificador "mytest", primero se ve en el objeto document, y si no se encuentra allí se ve en el objeto window.

Se puede acceder a la función, incluso con el nombre del formulario en conflicto si se especifica que es en el objeto window:

<a href="#" onClick="window.mytest();">Click Me</a> 
+2

También depende del navegador. IE contamina el espacio de nombre global con miembros para cada elemento en la página que declara un ID o un atributo NAME. No hace falta decir que causa muchos problemas. Dicho esto, debido a la necesidad de admitir IE en la mayoría de los casos, lo mejor es que intentes y asegúrate de que los nombres de tus funciones no colisionen con los valores de nombre/identificación de los elementos en tu página. – scunliffe

+0

@Scunliffe: en realidad, en este caso, otros navegadores se ven afectados. También tenga en cuenta que IE da prioridad a los nombres definidos en javascript. Solo cuando la búsqueda javascript estándar para un nombre en el alcance aparece sin nada, IE intenta resolver un nombre de la manera que sugiere. Por lo tanto, el caso de prueba en el ejemplo no habría fallado. – AnthonyWJones

7

Para añadir algún detalle de lo que sucede aquí es necesario comprender cadena de ámbitos de JavaScript.

ámbito de los objetos

Un objeto alcance está un objeto oculto crea cuando se ejecuta una función en la que las variables declaradas con var se colocan como propiedades, también cualquier llamado function dentro de la función de ejecución también se colocan como propiedades en el objeto de alcance

Cuando se solicita un identificador como mytest, javascript busca ese nombre adjunto al objeto de ámbito actual (por cierto, el objeto de ámbito también se conoce como el "contexto de ejecución").

cadena de ámbito

Cuando se declara una función dentro de una función del objeto alcance actual está unido a la función. Cuando esta función interna se está ejecutando (y, por lo tanto, tiene su propio objeto de alcance), la ejecución del código tiene acceso no solo al objeto de ámbito actual sino también al objeto de ámbito en el que se creó la función que se está ejecutando actualmente. Detener aquí, volver a leer la última oración. Esto se conoce como cadena de alcance , la cadena será tan profunda como haya funciones dentro de las funciones (esto sucede mucho cuando se utilizan marcos como JQuery).

Por lo tanto, cuando la búsqueda de un identificador falla en el objeto de ámbito actual, se examina el siguiente objeto de ámbito en la cadena. Sigue subiendo por la cadena hasta que golpea el objeto global (las funciones declaradas a nivel global tienen el objeto global como su objeto de alcance).

atributo de evento Weirdness

Cuando los navegadores ejecutar código dentro del texto de un atributo onclick como se trata a este código como si se tratara de una función. Sin embargo, los navegadores harán cosas extrañas con la cadena de alcance aparente adjunta a esta "función". Normalmente inyectan el elemento actual y el elemento del documento (y tal vez otros elementos intermedios) como si fueran objetos de alcance en la cadena de alcance.

Por ejemplo, cambie el código onclick en su ejemplo a "alert (href)". Verá la ruta a su página seguida de # en el cuadro de alerta. Esto se debe a que el elemento actual está en la cadena de alcance y, por lo tanto, href se resuelve con su propiedad href.

En el caso de la pregunta, el código llega al document en la cadena de alcance (que se coloca encima del objeto de ventana global) y encuentra el identificador "mytest" (que hace referencia a un formulario) y por lo tanto intenta usar el valor de eso como una función (y falla).

+0

Buena explicación, Anthony. Lo único que cambiaría es cambiar el nombre de lo que llamas "objeto de alcance" a "objeto de variable" (que es lo que realmente es :)). Otra cosa que es engañosa es que las "funciones nombradas" son miembros del objeto Variable. Ellos no son. Las declaraciones de funciones son, pero, por ejemplo, las expresiones de función no son, pero también podrían ser "nombradas" (iow, have identifier). Y, por último, cualquiera que esté interesado en determinar el alcance de los cuerpos de manejadores de eventos intrínsecos, debe leer este artículo (http://www.jibbering.com/faq/names/event_handler.html) que profundiza en un montón de detalles sobre el tema :) – kangax

+0

@ Kangax: Gracias por tus comentarios. Sí, estoy de acuerdo en que, estrictamente hablando, ECMA 262 usa el término "Objeto variable" pero es IMO un nombre tonto ya que implica que algún "objeto" "varía" de alguna manera. El término solo tiene sentido en el contexto de la especificación, lo cual está bien para los implementadores que explican esto a una computadora, pero es una basura para la comprensión interhumana. El término "objeto de alcance" se sostiene por sí mismo e implica que hay algún objeto relacionado con el alcance, también es fácil razonar que es probable que esté asociado con esa otra cosa llamada "cadena de alcance". – AnthonyWJones

+0

@Kangax: en lo que respecta a las "funciones nombradas", no estoy seguro de seguir su razonamiento. Pareces estar diciendo que puedes nombrar una expresión de función sin que ese nombre termine en el objeto Variable, pero no estoy seguro de que eso sea lo que realmente querías decir. – AnthonyWJones

Cuestiones relacionadas