2010-01-24 18 views
140

había tropezado con esta ordenada de acceso directo para la conversión de un DOM NodeList en una matriz regular, pero hay que admitir, que no entiendo completamente cómo funciona:Explicación de [] .slice.call en javascript?

[].slice.call(document.querySelectorAll('a'), 0) 

Por lo tanto, comienza con una matriz vacía [], a continuación, slice se utiliza para convertir el resultado de call en una nueva matriz, ¿sí?

El bit que no entiendo es el call. ¿Cómo se convierte eso document.querySelectorAll('a') de una NodeList a una matriz regular?

+2

'Array.prototype.slice.call (documento .querySelectorAll ('a')); 'es una forma adecuada de escribir el fragmento de código que escribió. – user544262772

Respuesta

112

Lo que está sucediendo aquí es que llame al slice() como si fuera una función de NodeList usando call(). Lo que hace slice() en este caso es crear una matriz vacía, luego iterar a través del objeto en el que se ejecuta (originalmente una matriz, ahora una NodeList) y seguir añadiendo los elementos de ese objeto a la matriz vacía que creó, que finalmente se devuelve. Aquí hay un article on this.

EDIT:

por lo que comienza con una matriz vacía [], luego corte se utiliza para convertir el resultado de la llamada a una nueva matriz, sí?

Eso no está bien. [].slice devuelve un objeto de función. Un objeto de función tiene una función call() que llama a la función que asigna el primer parámetro de call() a this; en otras palabras, hacer que la función crea que se está llamando desde el parámetro (NodeList devuelto por document.querySelectorAll('a')) en lugar de hacerlo desde una matriz.

+40

Tenga en cuenta también que, aunque esto es semánticamente equivalente a decir 'Array.prototype.slice.call (...)', en realidad crea una instancia de un objeto de matriz ('[]') solo para acceder a su método de división de sectores. Esa es una instanciación desperdiciada. En cambio, decir 'Array.prototype.slice.call (...)' es más claro, aunque agrega varios caracteres a su JS si está contando ... –

+0

Tenga en cuenta que esto funciona en IE 8 y debajo solo en objetos Array, por lo que no podrá clonar 'NodeList's –

+5

@quixoto' [] 'es más confiable ya que' Array' podría sobrescribirse en otra cosa. Si necesita reutilizar 'Array # slice', es una buena idea guardarlo en caché. –

22

Recupera la función slice de Array. Luego llama a esa función, pero utilizando el resultado de document.querySelectorAll como el objeto this en lugar de una matriz real.

88

En javascript, los métodos de un objeto pueden vincularse a otro objeto en tiempo de ejecución. En resumen, javascript permite que un objeto "prestado" el método de otro objeto:

object1 = { 
    name:'frank', 
    greet:function(){ 
     alert('hello '+this.name) 
    } 
}; 

object2 = { 
    name:'andy' 
}; 

// Note that object2 has no greet method. 
// But we may "borrow" from object1: 

object1.greet.call(object2); 

Los call y apply métodos de objetos de función (en javascript funciones son objetos así) le permite hacer esto. Entonces, en su código podría decir que la Nodelist está tomando prestado el método de corte de una matriz. Lo que hace la conversión es el hecho de que slice devuelve otra matriz como resultado.

+4

más 1 v.buenas realizaciones de idea genérica detrás de esto – Dexters

17

Es una técnica para convertir objetos tipo array a matrices reales.

Algunos de estos objetos son:

  • arguments en funciones
  • (recordar su contenido puede cambiar después de haber sido exagerado!así convertirlos a matriz es una manera de congelarlos)
  • colecciones jQuery, aka objetos jQuery (algunos DOC: API, type, learn)

Esto sirve para muchos fines, por ejemplo los objetos se pasan por referencia mientras las matrices se pasan por valor.

Además, tenga en cuenta que el primer argumento 0 se puede omitir, thorough explanation here.

Y para completar, también hay jQuery.makeArray().

8

¿Cómo se convierten document.querySelectorAll('a') de un NodeList a una serie regular?

Este es el código que tenemos,

[].slice.call(document.querySelectorAll('a'), 0) 

Lets desmontarlo primero,

[] // Array object 
.slice // Accessing the function 'slice' present in the prototype of Array 
.call // Accessing the function 'call' present in the prototype of function object(slice) 
(document.querySelectorAll('a'),0) 
    // 'call' can have arguments like, (thisArg, arg1,arg2...n). 
    // So here we are passing the 'thisArg' as an array like object, 
    // that is a 'nodeList'. It will be served as 'this' object inside of slice function. 
// And finally setting 'start' argument of slice as '0' and leaving the 'end' 
// argument as 'undefined' 

Paso: 1 Ejecución de call función

  • Dentro call, otra que el thisArg, el el resto de los argumentos se anexarán a una lista de argumentos.
  • Ahora la función slice se invocará mediante la unión de su valor como this thisArg (matriz como objeto procedían de document.querySelector) y con la lista de argumentos. es decir] argumento start que contiene 0

Paso: 2 Ejecución de slice función invocada dentro de call

  • start será asignado a una variable s como 0
  • desde end es undefined, this.length voluntad almacenarse en e
  • un vacío a RRay serán almacenados en una variable a
  • Después de hacer los ajustes por encima de la siguiente iteración se pasó

    while(s < e) { 
        a.push(this[s]); 
        s++; 
    } 
    
  • el llenado gama a que se obtiene es el resultado.

P.S Para una mejor comprensión de nuestro escenario de algunos pasos que son necesarios para nuestro contexto se ha hecho caso omiso del algoritmo original de call y slice.

+1

Muy buena explicación paso a paso. ¡Increíble! Gracias :) – Satyadev

+1

Agradable Explicación. – NaveenDA

1
[].slice.call(document.querySelectorAll('.slide')); 

1. The querySelectorAll() method returns all elements in the document that matches a specified selector(s). 

2. The call() method calls a function with a given this value and arguments provided individually. 

3. The slice() method returns the selected elements in an array, as a new array object. 

    so this line return the array of [object HTMLDivElement]. Here is the six div with classname "slide" so array length will be 6. 

<div class="slideshow"> 

    <div class="slide"> 
    first slider1 
    </div> 
    <div class="slide"> 
    first slider2 
    </div> 
    <div class="slide"> 
    first slider3 
    </div> 
    <div class="slide"> 
    first slider4 
    </div> 
    <div class="slide"> 
    first slider5 
    </div> 
    <div class="slide"> 
    first slider6 
    </div> 

</div> 

<script type="text/javascript"> 

    var arraylist = [].slice.call(document.querySelectorAll('.slide')); 

    alert(arraylist); 

</script> 
0

De ES6: Basta con hacer matriz con Array.from (element.children) o Array.from ({longitud: 5})