2009-06-29 10 views
6

Encienda su consola Firebug y pruebe esto.¿Es esto correcto? ¿Un error jQuery que borra el almacén de datos?

Compare esto:

$('body').data('x',1); 
$(thisx).remove(); 
console.log($('body').data('x')); 

a esto:

$('body').data('x',1); 
$(this.x).remove(); 
console.log($('body').data('x')); 

cuenta de la diferencia? Si thisx no está definido, arrojará inmediatamente un error de referencia. Si x es una propiedad indefinida de this, jQuery devolverá el documento como su conjunto de resultados en su lugar. Luego jQuery intentará eliminar su documento (lo que no puede), pero antes de hacerlo eliminará todos los datos adjuntos a cualquier elemento secundario del documento. Por lo tanto, borrando su almacén de datos.

Nota: this puede ser cualquier referencia de elemento u objeto. Solo necesita tener jQuery intente acceder a una propiedad indefinida.

(Hablando de un problema, falla silenciosamente, y estoy tratando de descubrir por qué mis datos faltan de repente. Lo rastreo a un caso especial donde una referencia de elemento no estaba definida en una situación específica.)

Así que a mis preguntas:

1) antes de enviarla un informe de error, ¿estoy analizando esto correctamente? Además, si alguien sabe que se trata de un problema conocido, házmelo saber. No pude encontrarlo en el rastreador de errores, pero la interfaz no es tan buena (o tal vez tengo esto mal).

2) ¿Por qué al final hay alguna diferencia? Supongo que thisx se evalúa inmediatamente, lo que causa la excepción, mientras que this.x es una referencia que se pasa y se evalúa en la función llamada, ¿verdad? (donde creo que la línea selector = selector || document; es la culpable.

3) Sugerencias sobre cómo manejar esto? Supongo que debería verificar que cualquiera/cada elemento de referencia o propiedad de un objeto (por ejemplo, cadenas de selector almacenadas) se define antes de pasarlo a jQuery al eliminar algo.

Respuesta

3

¿Por qué hay ninguna diferencia en última instancia?

Ambos thisx y this.x se evalúan cuando se llama a la función. El primero se refiere a un nombre de variable indefinido y arroja un error de referencia. El segundo accede a una propiedad indefinida de un objeto, lo que da como resultado el valor undefined. Así es como se comporta javascript en estos casos.

Ahora, cuando jQuery se llama en el segundo caso, la llamada $(this.x) evalúa a $(undefined) que es el mismo que si se hubiera hecho call $(). Como a JQuery le parece que no se proporcionó ningún argumento, en su lugar usa un valor predeterminado, y en este caso el valor predeterminado es document. Luego continúa tratando de eliminar document, ya que efectivamente se llamó como $().remove(), en cuyo caso esto sería de esperar.

Sugerencias para saber cómo manejar esto?

La diferencia con el ReferenceError es una diferencia fundamental de Javascript, no hay mucho que se pueda hacer al respecto. El comportamiento de JQuerys es desafortunado y una consecuencia de establecer los valores predeterminados en arg = arg||default. Se podría usar el usuario arguments.length para obtener el número real de parámetros de llamada, pero un cambio como este seguramente daría como resultado un lote de código interrumpido que dependía del valor predeterminado que se usa cuando se pasa undefined o 0, por lo que es poco probable que suceda.

3

Pruebe a escribir estos en la consola también (sin variables adicionales definidas de antemano):

> a 
    ReferenceError: Can't find variable: a 
> b = {} 
    Object 
> b.a 
    undefined 

uno es un error de JavaScript, uno en silencio vuelve indefinida (que jQuery interpretará como $() porque javascript y jQuery puede' t dicen las funciones $() y $(undefined) aparte)

esta es la forma javascript funciona, falla o función dejo abierto a debate, pero no creo que esto es culpa o problema de jQuery.

editar: ¿por qué jQuery tiene $() definido?

A partir de los documentos:

Por defecto, si no se especifica ningún contexto, $() busca los elementos DOM en el contexto del documento HTML actual . Si especifica un contexto, como un elemento DOM o un objeto jQuery, la expresión coincidirá con el contenido de ese contexto.

edición: los documentos se refieren al argumento pasado al contexto $(), no para llamar $() sin argumentos, por lo que no es relevante aquí.

también en cuenta que

$().get(0) == $("").get(0) 
+0

Creo que se vuelve problemático cuando undefined se convierte en el elemento del documento. ¿Hay otros casos en que esto sea útil en jQuery? –

+0

Hmm .... Me pregunto si se podría manejar mejor donde $ ('') se usa para ese caso. No es que lo cambien ahora por razones heredadas. Aún así, el código podría distinguir entre una cadena vacía y un valor indefinido. También podría verificar la longitud de los argumentos. Un valor indefinido aún tendría un arguments.length == 1, mientras que $() sería 0, ¿verdad? –

+0

ah, buen punto. No pensé en la variable de argumentos. – cobbal

Cuestiones relacionadas