2012-06-07 16 views
9

vi este script en otro lugar, y se comprobará cada casillas individuales:"[] .forEach"

[].forEach.call(document.querySelectorAll('input[type="checkbox"]'),function(el){ 
     el.checked=true; 
    } 
);​ 

que saben cómo utilizar forEach:

[0,1,2].forEach(function(num){ 
    console.log(num); 
}); 

//0 
//1 
//2 

Pero ahora , es [].forEach, y no hay nada dentro. Entonces, ¿por qué funciona? ¿Por qué no puedo hacer esto en su lugar?

document.querySelectorAll('input[type="checkbox"]').forEach(function(el){ 
     el.checked=true; 
    } 
);​ 
+0

Puedes. El primero termina siendo el mismo a través de la reflexión. Marque 'llamar' y' aplicar'. – entonio

+2

Tenga en cuenta que esta técnica '[] .forEach.call (nodeList, fn)' ** no funciona en IE8 **, por lo que no puede usarla en circunstancias generales. –

+1

Puede * técnicamente * agregar el método para usarlo en un resultado de 'querySelectorAll', pero es un camino plagado de peligros. 'NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;' –

Respuesta

10

JavaScript tiene funciones de primera clase; es decir, se tratan como objetos y pueden tener sus propias propiedades y métodos. El método construido en Function.call toma un parámetro this para la función como su primer argumento, y el resto de los argumentos se pasan a la función misma. La matriz [] no se usa, excepto como un medio para acceder al método Array.prototype.forEach (menos conciso, menos usado).

Es básicamente una reenlace de Array.forEach para usar en algo que no es una matriz, en este caso un NodeList. Si NodeList s ofrecen un método forEach, entonces sería equivalente a, y usted puede leerlo como este:

document.querySelectorAll('input[type="checkbox"]').forEach(function(el) { 
    el.checked = true; 
});​ 

Por lo tanto, un poco más en profundidad. call ejecutará una función con un contexto diferente. forEach itera sobre el contexto y llama a la función que se pasa como su argumento. Por lo tanto, se ejecutará someFunc.call(thisArg, otherArg) como si estuviera en el contexto de thisArg, como thisArg.someFunc(otherArg). Aquí está el ejemplo más sencillo:

function callMe(something) { 
    return something + this; 
} 

callMe('Hello'); // Hellonull or Hello[object Window] or something 
callMe.call({}, 'World'); // World[object Object] 

apply() funciona de la misma manera, pero se pasa una matriz de argumentos como el segundo argumento.

+0

Espera, ¿qué? ¿Entonces es un 'NodeList' en lugar de un' Array'? ¿No es 'NodeList' * is * an' Array'? –

+2

No, una 'NodeList' es * no * una' Matriz'. Sin embargo, fundamentalmente, se comporta como un 'Array' - tiene índices numéricos y una propiedad' length'. Simplemente no hereda los métodos estándar de 'Array'. Sin embargo, si un 'método' solo necesita indexación y' longitud', funcionaría, por lo que este fragmento de código en particular es válido. –

+0

@TikhonJelvis - Por lo tanto, es un 'Array' sin los métodos que debería tener un' Array'. Ya veo. –

3

Fíjate .call. Se aplica (establece this a) los resultados de document.querySelectorAll a forEach, por lo que itera sobre los resultados en lugar de la matriz (vacía) en el lado izquierdo del punto.

4

Esto es solo usando [] para obtener la función forEach. Una vez que tiene la función, usa .call para llamarlo como si fuera un método de document.querySelectorAll('input[type="checkbox"]').

Esto es útil porque el resultado de document.querySelectorAll no es una Array pero se comporta igual que uno, por lo que puede volver a utilizar los métodos estándar Array.

Cuando usa .call, el primer argumento se usa como el valor this. Es decir, en este fragmento particular, cada vez que se encuentra this dentro de la fuente forEach, se establece en document.querySelectorAll('input[type="checkbox"]').

No se puede llamar directamente porque document.querySelectorAll('input[type="checkbox"]').forEach(...querySelectorAll hace no devolver un objeto Array y por lo tanto no tiene un método forEach.Todo el asunto .call es solo una forma de evitar esto llamando al forEachcomo si fuera un método de NodeList, que es lo que realmente se devuelve.