2009-09-27 17 views
14

Los objetos jQuery actúan como matrices sin contaminar prototipos nativos. ¿Cómo se logra esto?¿Cómo los objetos jQuery imitan las matrices?

Sé que no se trata solo de objetos con teclas numéricas, por lo que quizás solo se trate de proporcionar los métodos respectivos (algo así como jQuery.prototype.indexOf = Array.prototype.indexOf).

Busqué en Google y miré la fuente, pero no pude encontrar una respuesta definitiva.

+3

¿Qué te hace creer que no se trata solo de objetos con teclas numéricas? – Marius

+2

Por un lado, Firebug muestra objetos jQuery como matrices, pero no como objetos creados manualmente, y dudo que tenga un manejo especial para jQuery. – AnC

Respuesta

26

Aunque los objetos jQuery actúan como matrices, en realidad son solo objetos tipo array. Un objeto similar a una matriz es un objeto que utiliza claves numéricas y que tiene una propiedad length, que es el mínimo necesario para la compatibilidad con el native array methods.

Dado que los objetos jQuery son solamente matriz similar y no reales Array objetos, las operaciones de matriz nativas (como indexOf o reverse) no puede ser llamado directamente. Sin embargo, puede usar Array.prototype o extender la funcionalidad de jQuery.

$('div').reverse(); // TypeError: $("div").reverse is not a function 

// we can use Array.prototype though 
Array.prototype.reverse.apply($('div')); 

// or we can extend jQuery very easily 
$.fn.reverse = Array.prototype.reverse; 
$('div').reverse(); // now it works! 

Tiene usted razón en el supuesto de que Firebug no incluye ninguna-carcasa especial para dar formato a los objetos jQuery. Una búsqueda rápida revela a relevant post en la lista de correo de Firebug. Suponiendo que la información sigue siendo correcta (la publicación es de enero) Firebug formateará un objeto como una matriz si tiene un longitud finita y un splice método.

JQuery cumple estos dos criterios, pero their implementation of splice no es más que una copia directa del método nativo Array. No está documentado, lo que significa que es solo para uso interno, o tal vez agregado únicamente con el propósito de engañar a Firebug para que formatee los objetos jQuery correctamente.

+0

Esto es excelente, ¡gracias! No quisiera agregar un método de empalme solo para que se vea bonito en Firebug, pero eso es solo un detalle menor. (PD: hay un error tipográfico en su publicación; usted menciona "slice" en lugar de "splice"). – AnC

+0

Gracias - corregido. Solo sugiero que el método 'splice' se haya agregado a jQuery específicamente para Firebug porque la rama 1.2 de jQuery _no_ expone dicho método. De hecho, recuerdo un corto período de tiempo en el que mis objetos jQuery no se formateaban como 'Arrays' en Firebug. Por supuesto, la introducción del método en 1.3 puede ser solo una coincidencia. –

+1

Gracias - esto fue interesante para el azar. Noto que el inspector web de Safari parece usar los mismos criterios: el objeto 'length' y el método' splice' para formatear objetos como matrices: 'var o; o = {length: 2, splice: function (x) {}}; '=>' [] '(tho 'firebug imprime rigurosamente:' [undefined, undefined] '). –

5

Buscar en código jQuery (desarrollo), la línea 139:

// Force the current matched set of elements to become 
// the specified array of elements (destroying the stack in the process) 
// You should use pushStack() in order to do this, but maintain the stack 
setArray: function(elems) { 
    // Resetting the length to 0, then using the native Array push 
    // is a super-fast way to populate an object with array-like properties 
    this.length = 0; 
    Array.prototype.push.apply(this, elems); 
     return this; 
}, 

Esto es porque cualquier resultado de las consultas de jQuery es matriz.

+0

Gracias. Lo había visto también, pero no parece ser suficiente: var MyObj = function (args) { this.length = 0; Array.prototype.push.apply (esto, argumentos); devuelve esto; }; var obj = new MyObj ("hello", "world"); – AnC

+1

¡No devuelva 'this' de un constructor! Además, 'var' establece una variable, pero no devuelve un valor; si está ejecutando ese fragmento en una herramienta similar a Firebug: 'var MyObj = function (args) {this.length = 0; Array.prototype.push.apply (esto, argumentos); }; obj = new MyObj ("hello", "world"); ' –

+0

Estoy confundido: si no es un constructor," este "no será el objeto (solo ventana) sin embargo !? ¿Puedes proporcionar una muestra de trabajo? – AnC

Cuestiones relacionadas