Ответ 1
Выбор DOM с помощью querySelectorAll()
Браузеры имеют несколько способов выбора элементов из DOM, но, возможно, наиболее гибким и удобным является querySelectorAll
. Он позволяет использовать селектор стиля CSS для захвата всех соответствующих элементов из заданного корня.
В вашем случае это будет выглядеть так:
document.querySelectorAll("button");
Сокращение querySelectorAll()
Как ни крути, это немного многословно, поэтому нередко создавать функцию обертывания, которая сокращает ее. Это то, что мы сделаем здесь, указав ему имя Q
.
function Q(root, selector) {
if (typeof root === "string") {
selector = root
root = document
}
return root.querySelectorAll(selector)
}
Первый аргумент - это контекст, из которого вы делаете выделение, а второй - селектор. Если вы передаете только строку, она будет использовать document
в качестве контекста.
Итак, теперь ваш выбор DOM будет таким, который мы будем использовать в дальнейшем:
Q("button");
Заимствование Array.prototype.forEach
Довольно простой способ создания функциональной циклической конструкции - заимствовать forEach
метод Array.prototype
и вызвать его на сбор элементов с помощью функции .call()
метод следующим образом:
Array.prototype.forEach.call(Q("buttons"), function(el) {
el.style.background = "red";
});
Или в самых современных браузерах мы можем использовать функции стрелок, чтобы немного сократить его:
Array.prototype.forEach.call(Q("buttons"), el => el.style.background = "red");
Связывание и кэширование заимствованного .forEach()
Задолженность .forEach()
может быть сокращена, если в начале вашего приложения вы используете прототип функции bind()
для привязки .forEach()
к значению this
.call()
.
const each = Function.call.bind(Array.prototype.forEach);
Таким образом вы можете просто называть его как функцию, которая получает коллекцию элементов в качестве первого аргумента.
each(Q("button"), function(el) {
el.style.background = "red";
});
Или снова используя функцию стрелки в некоторых из новейших браузеров:
each(Q("button"), el => el.style.background = "red");
Использование Array.from()
Был также введен метод Array.from
, чтобы легко преобразовывать объекты, подобные массиву, в реальные массивы. Это позволит вам напрямую использовать .forEach()
и может быть исправлена в устаревшие браузеры с помощью простого polyfill (см. Ссылку docs).
Array.from(Q("button")).forEach(function(el) {
el.style.background = "red";
});
Если вы поместите вызов Array.from
непосредственно в нашу функцию Q
сверху, вы сможете напрямую вызвать .forEach()
.
Q("button").forEach(function(el) {
el.style.background = "red";
});
Использование цикла for-of
В последних браузерах вы можете использовать for-of
loop, делая все очень короткое и чистое:
for (const el of Q("button")) {
el.style.background = "red";
}
Таким образом, нет необходимости конвертировать в Array
или использовать .forEach
.
Трансляция современного кода
В приведенных выше примерах, которые требуют самых современных браузеров, доступны транспилеры (например Babel), которые будут переводить последние стандартов в код, который будет работать в старых браузерах.
Создание пользовательского each()
В качестве побочного примечания, если вы хотите, чтобы this
ссылался на текущий элемент или имел какое-либо другое конкретное поведение, вот базовая реализация each
, которая получает коллекцию и обратный вызов.
function each(a, callback) {
for (var i = 0; i < a.length; i++) {
callback.call(a[i], a[i], i, a);
}
}
Хотя использование this
таким образом вообще не требуется, поскольку у вас уже есть элемент как параметр.