Търсих как да повторя NodeLists и попаднах на следния код.
var nodesArray = Array.prototype.slice.call(nodeList);
nodesArray.forEach(function(node) {
//...
})
Каква е целта на извикването на Array.prototype.slice
срещу NodeList?
Търсих как да повторя NodeLists и попаднах на следния код.
var nodesArray = Array.prototype.slice.call(nodeList);
nodesArray.forEach(function(node) {
//...
})
Каква е целта на извикването на Array.prototype.slice
срещу NodeList?
Каква е целта на извикването на
Array.prototype.slice
срещу NodeList?
Методът Array#slice
"връща плитък копиране на част от масив в нов обект на масив".
Методът Function#call
"извиква функция с дадена тази стойност и аргументи, предоставени индивидуално".
Тъй като масивите са обекти, всички имена на свойства на обекти се съхраняват като низове и всички списъци с възли съхраняват своите елементи с последователно номерирани имена на свойства (отново съхранени като низове), списъците с възли могат да се използват като this
стойност за методите на масива.
Създаването на плитко копие на NodeList като масив ви позволява да използвате други методи за масив в новосъздадения масив, без да използвате Function#call
.
Много съвременни браузъри са внедрили NodeList#forEach
, въпреки че методът е все още е препоръка за кандидат и не е включен в спецификацията на този етап. Препоръчвам да използвате този метод внимателно, а не в отворената мрежа, докато не достигне по-стабилно състояние.
Ето някои други примери за Array методи, които се извикват с NodeList като цел:
// Convert to an array, then iterate
const nodeArray = Array.prototype.slice.call(nodeList)
nodeArray.forEach(doSomething);
// Iterate NodeList directly without conversion
Array.prototype.forEach.call(nodeList, doSomething);
// Perform operation on each element in NodeList, output results to a new Array
Array.prototype.map.call(nodeList, function(item) {
return item;
}).forEach(doSomething);
// Filter NodeList, output result to a new Array
Array.prototype.filter.call(nodeList, function(item) {
return /* condition */;
}).forEach(doSomething);
Има много други начини, по които можете да итерирате NodeList, които не изискват използването на Array методи, ето още няколко примера:
Можете да използвате добър старомоден for цикъл, да започнете от нула и да циклите, докато стигнем до края на масива. Този метод съществува от векове и се използва редовно и днес. Този метод е донякъде по-малко четлив от другите методи, споменати тук, но всичко се свежда до това какво е по-лесно за вас да пишете.
for(let i = 0; i < nodeList.length; ++i) doSomething(nodeList[i]);
Използването на обратен цикъл (където е възможно) може да спести намаляване на времето за изпълнение поради липса на условна оценка. Всъщност някои IDE ще преобразуват предишния цикъл в следната структура по подразбиране.
for(let i = nodeList.length; i--;) doSomething(nodeList[i]);
Можете да използвате цикъл while, който очаква условен оператор като свой параметър. Ако NodeList.item(n)
е извън границите на NodeList, той ще върне null, което ще прекрати цикъла.
let i = 0, node;
while((node = nodeList.item(i++))) doSomething(node);
Можете да направите същото с for цикъл в условното:
let node;
for(let i = 0; (node = nodeList.item(i)); i++) doSomething(node);
Можете да използвате for...in цикъл с Object.keys()
. Обърнете внимание, че трябва да използвате Object.keys
, когато използвате for...in цикъл, защото в противен случай той ще повтори неизброимите свойства, както и изброимите.
Методът Object.keys() връща масив от собствените изброими свойства на даден обект в същия ред като този, предоставен от for...in цикъл (разликата е, че for-in цикълът изброява свойствата във веригата на прототипа като добре).
От: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
for(var i in Object.keys(nodeList)) doSomething(nodeList[i]);
Можете да използвате for...of
цикъл (ECMAScript 2015+), като извлечете функцията Iterator от Array() и я приложите към NodeList. Това ще работи и за повечето други употреби на обект, стига свойствата да са изброими.
nodeList[Symbol.iterator] = [][Symbol.iterator];
for(node of nodeList) doSomething(node);
Ако приложите Array Iterator към прототипа на класа NodeList, когато се създаде нов екземпляр на NodeList, той винаги ще може да се повтаря. Въпреки това, не е препоръчително да се разширяват естествени прототипи.
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
for(node of nodeList) doSomething(node);
Всички тези отговори са остарели. Всъщност можете да използвате forEach
в NodeList в съвременните браузъри!
Така че просто използвайте forEach!
Тъй като slice
връща копие на всеки подобен на масив аргумент като нов обект на масив, което е точно това, от което се нуждаем. Можем също толкова лесно да използваме concat
.
concat
ще работи, бих си помислил, че това е един метод на масив, който вероятно ще се провали в тази ситуация? Бих искал да видя как да. jsfiddle.net/Xotic750/k552C
- person Xotic750; 21.02.2014