2015-06-15 6 views
7

Mozilla заявляет, что «для циклов для петли над объектами NodeList правильно». (источник: https://developer.mozilla.org/en-US/docs/Web/API/NodeList) Однако это не работает в Chrome 43. Является ли это неправильной документацией или ошибкой браузера?for loop querySelectorAll

Скопированная пример кода, используемого на странице с флажками:

var list = document.querySelectorAll('input[type=checkbox]'); 
for (var item of list) { 
    item.checked = true; 
} 
+0

Можем ли мы иметь немного больше контекста? Можете ли вы привести нам пример или что-нибудь еще? – Xufox

+0

Я хотел бы знать, что именно не работает в Chrome. Вызывает ли синтаксическая ошибка? Не проверяет ли этот флажок? – Xufox

+2

['for..of' loops] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) поддерживает только объекты, которые [реализованы как итераторы ] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), содержащий ключ/метод 'Symbol.iterator'. В настоящее время, в Chrome, 'console.log (Symbol.iterator в списке); // false. –

ответ

1

Поскольку я успешно использовал for..of в Gecko итерировать NodeList с, кажется, это браузер ошибка, или, по крайней мере, браузер отсутствие ,

Фактические рабочий код из userscript настоящего времени я использую:

let llnk = document.querySelectorAll("div#threadlist a.threadtitle_unread"); 
for (let lnk of llnk) { 
    //... 
} 

(Это также использует let, но это другая история).

6

Документов правильно, но я бы не назвал это ошибка. Скорее это «еще не реализованная функция».

Для этого нет стандарта, и по-прежнему активно обсуждается вопрос о том, как DOM должен интегрироваться с ES6. Обратите внимание на то, что ясно , чтоquerySelectorAll должен вернуть что-то итерацию, который может быть использован в for of цикла (как общие требования ожиданий), но это не ясно как, что должно произойти (Пусть NodeList реализовать Iterable интерфейс? Пусть некоторые Elements collection подкласс Array?).

1

Try используя Array.prototype.entries()

var list = [].entries.call(document.querySelectorAll("input[type=checkbox]")); 
 

 
for (item of list) { 
 
    item[1].checked = true; 
 
};
<input type="checkbox" /><input type="checkbox" />

Вы можете также использовать Array.prototype.values()

var list = [].values.call(document.querySelectorAll("input[type=checkbox]")); 
 

 
for (item of list) { 
 
    item.checked = true; 
 
};
<input type="checkbox" /><input type="checkbox" />

0

Вы можете использовать Array.from

let _list = document.querySelectorAll('input[type=checkbox]'); 

let list = Array.from(_list); 

for (let item of list) { 
    //... just like an array 
    item.checked = true 
} 

или покороче

let list = document.querySelectorAll('input[type=checkbox]'); 

for (let item of Array.from(list)) { 
    item.checked = true 
} 

Важное примечаниеArray.from был введен в Chrome 45 source.

+0

Как это лучше? Вам нужно вызвать Array.from каждый раз. –

+0

Да, это правда, что вы должны каждый раз вызывать 'Array.from' (и, возможно, включать в себя полиполк), но с помощью этого метода вы не пытаетесь расширить DOM. –

+0

Что это связано с расширением DOM? –

0

Это то, что я делаю, для другого подхода

Array.prototype.forEach.call(document.querySelectorAll("input[type=checkbox]"),function(ele,idx) 
{ 
    ele.checked = true; 
} 

хорошее от IE9 и выше поддержки

0

Native Symbol.iterator для NodeList был added к WHATWG's DOM spec в 2014 г.

К сожалению, Chrome 51 - первая версия Chrome для ее поддержки, и ее бета-версия только что была выпущена во время написания этого ответа. Кроме того, в любой версии Internet Explorer или Edge нет поддержки.

Чтобы добавить поддержку Symbol.iterator для NodeList во всех браузерах в коде, просто используйте следующую polyfill:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; 
1

Вот еще одно решение для современной эпохи:

[...document.querySelectorAll("input[type=checkbox]")].forEach(node => { 
    node.textContent = "foo"; 
}); 

Это имеет преимущество spread operator, который поддерживается в Google Chrome 46+, Firefox 16+ и Edge, и просто для удовольствия arrow function.

+0

Какова цель восстановления массива? –

+0

Результат 'querySelectorAll' - это NodeList, а не массив. Преобразуя его, мы можем легко перебрать его. –

+0

Какая разница теперь? Они оба итерабельны. –

0

У меня была эта проблема. Оказывается, мой был вызван вызовом Promise.all() с параметрами вместо массива. Например:

До: Promise.all(p1, p2)

После: Promise.all([p1, p2])

Надеется, что это поможет кому-то.

+0

Что это связано с NodeList? –