[]es una matriz
Esta matriz no se usa en absoluto.
Se está poniendo en la página, porque el uso de una matriz le da acceso a prototipos de matriz, como .forEach.
Esto es más rápido que escribir Array.prototype.forEach.call(...);
A continuación, forEachhay una función que toma una función como entrada ...
[1,2,3].forEach(function (num) { console.log(num); });
... y para cada elemento en this(donde thises como una matriz, en el sentido de que tiene un lengthy puede acceder a sus partes como this[1]) pasará tres cosas:
- el elemento en la matriz
- el índice del elemento (pasaría el tercer elemento
2)
- una referencia a la matriz
Por último, .calles un prototipo que tienen funciones (es una función que se llama a otras funciones).
.calltomará su primer argumento y lo reemplazará thisdentro de la función regular con lo que haya pasado call, como primer argumento ( undefinedo nulllo usará windowen JS cotidiano, o será lo que haya pasado, si está en "modo estricto"). El resto de los argumentos se pasarán a la función original.
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
Por lo tanto, está creando una forma rápida de llamar a la forEachfunción, y está cambiando thisde la matriz vacía a una lista de todas las <a>etiquetas, y para cada <a>orden, está llamando a la función proporcionada.
EDITAR
Conclusión lógica / limpieza
A continuación, hay un enlace a un artículo que sugiere que descartemos los intentos de programación funcional y nos apeguemos al bucle manual, en línea, siempre, porque esta solución es hack-ish y antiestética.
Yo diría que, si bien .forEaches menos útil que sus homólogos, .map(transformer), .filter(predicate), .reduce(combiner, initialValue), todavía sirve los propósitos cuando todo lo que realmente quiere hacer es modificar el mundo exterior (no la matriz), n-veces, mientras que tener acceso a cualquiera arr[i]o i.
Entonces, ¿cómo lidiamos con la disparidad, ya que Motto es claramente un tipo talentoso y conocedor, y me gustaría imaginar que sé lo que estoy haciendo / a dónde voy (de vez en cuando ... ... otro veces es el aprendizaje de cabeza)?
La respuesta es en realidad bastante simple, y algo que tío Bob y Sir Crockford se enfrentarían a ambos, debido a la supervisión:
limpiarlo .
function toArray (arrLike) { // or asArray(), or array(), or *whatever*
return [].slice.call(arrLike);
}
var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);
Ahora, si se pregunta si necesita hacer esto, usted mismo, la respuesta puede ser no ...
Esto es exactamente lo que hacen ... ... todas las (?) Bibliotecas con características de orden superior en estos días.
Si está usando lodash o subrayado o incluso jQuery, todos tendrán una forma de tomar un conjunto de elementos y realizar una acción n veces.
Si no estás usando algo así, entonces, por supuesto, escribe el tuyo.
lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
var others = lib.array(arguments, 1);
return others.reduce(appendKeys, subject);
};
Actualización para ES6 (ES2015) y más allá
No solo un método auxiliar slice( )/ array( )/ etc facilitará la vida de las personas que desean usar listas tal como usan las matrices (como deberían), sino también para las personas que tienen el lujo de operar en navegadores ES6 + de usuarios relativamente cercanos. futuro, o de "transpilar" en Babel hoy, tiene características de lenguaje incorporadas, que hacen innecesario este tipo de cosas.
function countArgs (...allArgs) {
return allArgs.length;
}
function logArgs (...allArgs) {
return allArgs.forEach(arg => console.log(arg));
}
function extend (subject, ...others) { /* return ... */ }
var nodeArray = [ ...nodeList1, ...nodeList2 ];
Súper limpio y muy útil.
Busque los operadores Rest and Spread ; pruébelos en el sitio de BabelJS; Si su pila tecnológica está en orden, úsela en producción con Babel y un paso de compilación.
No hay una buena razón para no poder usar la transformación de no matriz a matriz ... ... simplemente no ensucie su código haciendo nada más que pegar esa misma línea fea, en todas partes.
.callno cambiar el valor dethis, por lo que usted está utilizandocallcon el forEach. Si forEach se ve asíforEach (fn) { var i = 0; var len = this.length; for (; i < length; i += 1) { fn( this[i], i, this ); }, al cambiarthisdiciendo,forEach.call( newArrLike )significa que usará ese nuevo objeto comothis..callno cambia el valor delthisinterior de lo que le pasaforEach,.callcambia el valor delthisinterior de forEach . Si no está seguro de por quéthisno se pasa deforEachla función a la que desea llamar, debe buscar el comportamientothisen JavaScript. Como una adición, aplicable solamente aquí (y mapa / filtro / reducir), hay un segundo argumento paraforEach, que establecethisdentro de la funciónarr.forEach(fn, thisInFn)o[].forEach.call(arrLike, fn, thisInFn);o uso justo.bind;arr.forEach(fn.bind(thisInFn));[]solo está allí como una matriz, para que pueda usar.callel.forEachmétodo y cambiarthisel conjunto al que desea trabajar..callse ve así:function (thisArg, a, b, c) { var method = this; method(a, b, c); }excepto que hay magia negra interna para establecerthisdentro demethodigual a lo que pasóthisArg.El
querySelectorAllmétodo devuelve aNodeList, que es similar a una matriz, pero no es exactamente una matriz. Por lo tanto, no tiene unforEachmétodo (que los objetos de matriz heredan a través deArray.prototype).Dado que a
NodeListes similar a una matriz, los métodos de matriz realmente funcionarán en ella, por lo que al usarlos[].forEach.callinvocas elArray.prototype.forEachmétodo en el contexto de laNodeList, como si hubieras podido hacerlo simplementeyourNodeList.forEach(/*...*/).Tenga en cuenta que el literal de matriz vacía es solo un acceso directo a la versión expandida, que probablemente también verá con bastante frecuencia:
fuente
[].forEach.call(['a','b'], cb)más['a','b'].forEach(cb)en aplicaciones cotidianas con matrices estándar, solo cuando se intenta iterar sobre estructuras similares a matrices que no tienenforEachsu propio prototipo? ¿Es eso correcto?[].forEach():)var section = document.querySelectorAll(".section"); section.forEach((item)=>{ console.log(item.offsetTop) })funciona bienforEachcon matrices, pero no con objetos NodeList)Las otras respuestas han explicado este código muy bien, así que solo agregaré una sugerencia.
Este es un buen ejemplo de código que debe ser refactorizado por simplicidad y claridad. En lugar de usar
[].forEach.call()oArray.prototype.forEach.call()cada vez que haga esto, realice una función simple:Ahora puede llamar a esta función en lugar del código más complicado y oscuro:
fuente
Se puede escribir mejor usando
Lo que hace es
document.querySelectorAll('a')devolver un objeto similar a una matriz, pero no hereda delArraytipo. Entonces llamamos alforEachmétodo desde elArray.prototypeobjeto con el contexto como el valor devuelto pordocument.querySelectorAll('a')fuente
Básicamente es lo mismo que:
fuente
Quiere actualizar esta vieja pregunta:
La razón para usar
[].foreach.call()para recorrer elementos en los navegadores modernos ha terminado. Podemos usardocument.querySelectorAll("a").foreach()directamente.fuente
Una matriz vacía tiene una propiedad
forEachen su prototipo que es un objeto Function. (La matriz vacía es solo una manera fácil de obtener una referencia a laforEachfunción que tienen todos losArrayobjetos). Los objetos de función, a su vez, tienen unacallpropiedad que también es una función. Cuando invocas la función de una Funcióncall, ejecuta la función con los argumentos dados. El primer argumento se conviertethisen la función llamada.Puede encontrar documentación para la
callfunción aquí . La documentación paraforEachestá aquí .fuente
Solo agrega una línea:
¡Y voilá!
Disfruta :—)
Advertencia: NodeList es una clase global. No use esta recomendación si escribe una biblioteca pública. Sin embargo, es una forma muy conveniente de aumentar la autoeficacia cuando trabaja en el sitio web o en la aplicación node.js.
fuente
Solo una solución rápida y sucia que siempre uso. No tocaría prototipos, como buena práctica. Por supuesto, hay muchas maneras de mejorar esto, pero se entiende la idea.
fuente
[]siempre devuelve una nueva matriz, es equivalentenew Array()pero se garantiza que devolverá una matriz porqueArrayel usuario podría sobrescribirla mientras[]que no puede. Entonces, esta es una forma segura de obtener el prototipo deArray, luego, como se describe,callse utiliza para ejecutar la función en la lista de nodos de matriz (esto).fuente
[], de hecho, siempre devolverá una matriz, mientras quewindow.Arraypuede sobrescribirse con cualquier cosa (en todos los navegadores antiguos), también puedewindow.Array.prototype.forEachsobrescribirse con cualquier cosa. No hay garantía de seguridad en ninguno de los casos, en los navegadores que no admiten getters / setters o sellado / congelación de objetos (la congelación causa sus propios problemas de extensibilidad).prototypeo métodos de TI:forEach.Norguard explicó QUÉ
[].forEach.call()hace y James Allardice POR QUÉ lo hacemos: porque querySelectorAll devuelve unNodeListque no tiene un método forEach ...A menos que tenga un navegador moderno como Chrome 51+, Firefox 50+, Opera 38, Safari 10.
Si no, puede agregar un Polyfill :
fuente
Mucha información buena en esta página (ver respuesta + respuesta + comentario ), pero recientemente tuve la misma pregunta que el OP, y me tomó un poco de tiempo para obtener la imagen completa. Entonces, aquí hay una versión corta:
El objetivo es usar
Arraymétodos en una matrizNodeListque no tenga esos métodos en sí.Un patrón anterior cooptó los métodos de Array a través de
Function.call(), y usó una matriz literal ([]) en lugar deArray.prototypeporque era más corto de escribir:Un patrón más nuevo (post ECMAScript 2015) es usar
Array.from():fuente