2011-03-31 20 views
34

¿Alguien puede decirme qué tipo de objeto es NodeList? Leí que es un objeto similar a un array y que se puede acceder a través de la notación de corchetes, por ejemplo var a = someNode.childNode[0];. ¿Cómo es esto posible ya que a través de la notación de corchetes solo podemos acceder a las propiedades de un objeto, y como sé que no podemos tenerObjeto NodeList en javascript

+0

pregunta bonita y clara :) – Mahi

Respuesta

8

NodeLists "en vivo", es decir que se actualizan cuando la estructura del documento cambia de tal manera que siempre están al día con la información más precisa. En realidad, todos los objetos NodeList son consultas que se ejecutan contra el DOM cada vez que se accede a ellos.

En cualquier momento que desee repetir un NodeList, lo mejor es inicializar una segunda variable con la longitud y luego comparar el iterador a esa variable:

var divs = document.getElementsByTagName("div"); 

for (var i=0, lens=divs.length; i < len; i++){ 
    var div = document.createElement("div"); 
    document.body.appendChild(div); 
} 

NodeList es una matriz como la estructura, pero no es en realidad una matriz. Puede acceder a valores de matriz a través de la notación de corchetes.

+0

Lo que acaba de responder está escrito en el libro que estoy leyendo. No puedo decir lo que significa array-like. EcmaScript no especifica nada como esto. Supongo que es una técnica de implementación. – ppoliani

+0

No está en ECMA su especificación DOM. Puede iterar sobre él como una matriz (notación de corchetes) pero no puede usar métodos de Array como push(), splice() o reverse() para manipularlo. –

+0

Es decir, se ejecuta en código de navegador (por ejemplo, C++)? – ppoliani

9

NodeList no es un objeto JavaScript central, es provisto por el navegador con el DOM. Piense en una función que devuelve una interfaz a un objeto dinámico o en vivo, por lo que paraEach() no está disponible, pero puede convertirlo en una matriz real para tener una instantánea con p. Ej.

// turns nodelist into an array to enable forEach 
function toArray(list) { 
    var i, array = []; 
    for (i=0; i<list.length;i++) {array[i] = list[i];} 
    return array; 
} 

Detalles: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-536297177

+0

Bueno, supongo que está implementado en un lenguaje como C++. Aun así, ¿cómo se comunican con el código JavaScript? – ppoliani

+0

@ user512783: Eso depende del navegador y del motor de JavaScript. ¿Por qué quieres saber esto? – Martijn

+0

quería saber si la DOM API está escrita en EcmaScript, pero como yo entiendo, no es así. – ppoliani

37

NodeList es un objeto de host y no está sujeto a las reglas habituales que se aplican a objetos JavaScript nativas. Como tal, debe apegarse a la API documentada para ello, que consiste en una propiedad length y acceder a sus miembros a través de la sintaxis de acceso a la propiedad de corchetes. Se puede utilizar esta API para crear una Array que contiene una instantánea de los miembros del NodeList:

var nodeList = document.getElementsByTagName("div"); 
var nodeArray = []; 
for (var i = 0; i < nodeList.length; ++i) { 
    nodeArray[i] = nodeList[i]; 
} 
+2

¿Significa esto que nodeList no puede atravesarse mediante un bucle forin? – Triztian

+1

@Triztian: De hecho lo hace. Al menos, no hay garantía de que funcione, y creo que no en IE. –

+1

No funcionará tampoco en Google Chrome, debe usar la propiedad de longitud y acceder a los elementos como si fuera una matriz. – Triztian

8

JavaScript es comparable al alcohol, puede coaccionar:

var links = document.getElementsByTagName('a'); 
Array.prototype.slice.call(links).forEach(function(anchor, index, arr) { 
    anchor.addEventListener('click', onClickFN, false); 
}); 
+0

... o simplemente 'Array.prototype.forEach.call (enlaces, función() {})';) – yckart

+0

o simplemente '[] .slice.call' – Mahi

37

Un NodeList es colección de DOM elements. Es como una matriz (pero no lo es). Para trabajar con él, debes convertirlo en una matriz de JavaScript normal. El siguiente fragmento puede hacer el trabajo por usted.

const nodeList = document.getElementsByClassName('.yourClass'), 
     nodeArray = [].slice.call(nodeList); 
+0

' [] .slice.call (nodeList) 'funciona como un encanto para mi Me encantaría saber por qué/cómo funciona. – Lounge9

+4

básicamente javascript trata la lista de nodos como una matriz porque está configurando el contenido de la matriz vacía para que sea la lista de nodos utilizando el método de llamada. luego, simplemente el método de corte devuelve una copia exacta de sí mismo (cuando se usa sin argumentos). espero que esto responda tu pregunta (: – brielov

+0

brillantemente, gracias de nuevo! – Lounge9

6

Listas de nodos a menudo se implementan como iteradores nodo con un filtro. Esto significa que obtener una propiedad como la longitud es O(n), e iterar sobre la lista volviendo a verificar la longitud será O (n^2).

var paragraphs = document.getElementsByTagName('p'); 
for (var i = 0; i < paragraphs.length; i++) { 
    doSomething(paragraphs[i]); 
} 

Es mejor hacer esto en su lugar:

var paragraphs = document.getElementsByTagName('p'); 
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) { 
    doSomething(paragraph); 
} 

Esto funciona bien para todas las colecciones y matrices, siempre y cuando la matriz no contiene cosas que son tratadas como falso booleano.

En los casos en los que itera sobre los nodos secundarios, también puede usar las propiedades firstChild y nextSibling.

var parentNode = document.getElementById('foo'); 
for (var child = parentNode.firstChild; child; child = child.nextSibling) { 
    doSomething(child); 
} 
+0

Esta respuesta podría beneficiarse de una explicación de lo que son O (n) y O (n^2). – TylerH

+2

@TylerH, agregó un enlace de Wikipedia. –

+1

Ehm, no solo * valores booleanos falsos * romperán el ciclo, todos los valores * falsey * ('undefined',' null', '0' etc.) serían ... – yckart