2012-01-09 18 views
8

Tengo otra pregunta sobre la arquitectura de jQuery. $('div') construye un nuevo objeto jQuery:¿Por qué es posible consultar jQuery ('div') como una matriz?

$('div') instanceof jQuery; // true 

Me gustaría saber por qué es posible consultar como si fuera una matriz, acabase no es una matriz?

$('div')[0]; // returns the first div in the document as a DOM node. 
$.isArray($('div')); // false 

Me encanta esta sintaxis, se ve tan limpio! También me di cuenta de esto devuelve los nodos DOM como una matriz:

console.log($('div')); 

Puede alguien explicar cómo implementar este comportamiento a mis propios objetos?


Mi propio enfoque era hacer una matriz con algunos métodos como éste:

var a = ['a', 'b', 'c']; 
a.method = function(){ return 'test'; }; 
a; // ['a', 'b', 'c'] 
a[0]; // 'a' 
a.method(); // 'test' 

Sin embargo, esto no parece ser el camino jQuery lo hace, ya que es en realidad una matriz:

$.isArray(a); // true 

Me gustaría saber cómo jQuery hace esto para aprender y ver si es una solución mejor que la mía.

+0

* Se puede acceder a cualquier propiedad * usando notación '[] '. No solo índices. Así que al igual que '$ ('div') [0]', puedes hacer '$ ('div') ['jquery']', que te dará el número de versión de jQuery. –

+0

@amnotiam Lo sé. Pero cuando imprimo objetos usuales en las consolas, no generan una matriz. –

+0

Ah, si está preguntando específicamente sobre la salida de la consola, entonces realmente es solo la consola que adivina lo que usted le dio. [La respuesta de jay] (http://stackoverflow.com/a/8793090/1106925) muestra lo que suelen hacer las consolas. –

Respuesta

10

Un objeto jQuery es lo que llamamos Array-like object. Eso significa que, de hecho, es un objeto "verdadero" (de hecho, todas las "matrices" son objetos en ECMAscript), pero posee ciertas propiedades que lo hacen parecer una matriz "verdadera". Estas propiedades son

  • como un .length propiedad
  • que posee el método .splice()

esos dos hechos son lo suficientemente que la mayoría de los motores de js consolas interpretate ese objeto como matriz.

Ejemplo:

var myObject = { }, 
    push = Array.prototype.push; 

myObject.aNiceFunction = function() { 
    console.log(this); 
}; 

push.call(myObject, document.getElementById('foo')); 
push.call(myObject, document.getElementById('bar')); 

myObject.splice = Array.prototype.splice; 

Si ahora registramos nuestro objeto

console.log(myObject); 

obtenemos los jQuery'ish típicos resultan

[div#foo, div#bar] 

See that in action

pero todavía podemos llamar a nuestro método .aNiceFunction() en ese objeto. Al insertar nuevos elementos con el método Array.prototype.push() en nuestro objeto, ECMAscript indexará automáticamente esos elementos para nosotros. Esa fue una breve descripción de lo que ocurre debajo de la cubierta de jQuery.

Una palabra más acerca de los "arrays" en ECMAScript. No hay matrices reales en este idioma (si nos olvidamos de typed arrays por un segundo). Solo hay Object. Si tenemos un objeto que hereda de Array.prototype, casi lo llamaríamos una matriz. Todo lo que nos queda por hacer es establecer la propiedad .length en 0.

+2

Los motores JS no interpretan nada como una matriz. JS _users_ interpretan cosas como matrices. :) – SLaks

+0

@SLaks: touchè. Lo que quería decir es que, por ejemplo, está "desconectado" por el objeto de la consola. – jAndy

+0

Esa es una función de la bonita impresora de Firebug/Chrome (que son usuarios de JS), no del motor JS. – SLaks

2

Los objetos jQuery son objetos similares a una matriz.

Un objeto similar a una matriz es un objeto ordinario que tiene las mismas propiedades que una matriz.
Una matriz como objeto tiene un length propiedad establecida en un número entero positivo, y propiedades denominadas 0, 1, ... length − 1 que contiene los objetos de matriz.

0

Los objetos jQuery son objetos "tipo array". Considere el siguiente código:

document.forms.length; // returns 1; 
document.forms[0]; // returns a form element. 
document.forms.join(", "); // throws a type error. this is not an array. 
typeof document.forms; // returns "object" 

La modificación de su código, se puede lograr este mismo efecto:

var a = 
{ 
    0: 'a', 
    1: 'b', 
    2: 'c', 
    length: 3, 
    method: function() { 
     return "test"; 
    } 
}; 
+0

'console.log (a)' imprime el objeto, no la matriz. Así que esta no parece ser la forma en que jQuery lo hace. Y, por cierto, no soy un principiante de JavaScript, sé cómo funcionan los objetos de JavaScript. –

1

El tratamiento de un objeto jQuery como un array es una aplicación de pato escribir. From Wikipedia:

En la programación de ordenador con los lenguajes de programación orientados a objetos, duck typing es un estilo de tipado dinámico en el cual la corriente conjunto de métodos y propiedades de un objeto determina la semántica válidos, en lugar que su herencia de un clase particular o implementación de una interfaz específica .

En otras palabras, no es importante que la función jQuery vuelven en realidad una instancia de Array, el tiempo que proporciona las propiedades necesarias (por ejemplolength, índices numéricos) y métodos para actúan como una matriz.

JavaScript tiene otros objetos tipo array. Por ejemplo, el objeto arguments tampoco es una matriz, pero tiene propiedades (como length) que le permiten simular que es así.

0

no estoy seguro de lo que esta locura "tipo array" es de las otras respuestas. No hay una terminología estándar para "tipo array".

La diferencia real aquí es la diferencia entre una matriz real, que es una colección de elementos frente a una lista enlazada que es una colección de referencias. En referencia al DOM, una lista vinculada se denomina apropiadamente lista de nodos.Estos articlea tiene más información:

http://www.mindcracker.com/Story/1016/interview-question-difference-between-linked-list-and-array.aspx

http://www.sitepoint.com/a-collection-is-not-an-array/

http://blog.duruk.net/2011/06/19/nodelists-and-arrays-in-javascript/

Cuestiones relacionadas