2012-06-07 5 views
9

Я видел этот сценарий где-то еще, и он будет проверять каждые отдельные флажки:"[] .forEach"

[].forEach.call(document.querySelectorAll('input[type="checkbox"]'),function(el){ 
     el.checked=true; 
    } 
);​ 

Я знаю, как использовать forEach:

[0,1,2].forEach(function(num){ 
    console.log(num); 
}); 

//0 
//1 
//2 

Но теперь , [].forEach, и внутри ничего нет. Так почему же он все еще работает? Почему я не могу это сделать?

document.querySelectorAll('input[type="checkbox"]').forEach(function(el){ 
     el.checked=true; 
    } 
);​ 
+0

Вы можете. Первый заканчивается тем же путем отражения. Проверьте 'call' и' apply'. – entonio

+2

Обратите внимание, что этот метод '[] .forEach.call (nodeList, fn)' не работает в IE8 **, поэтому вы не можете использовать его в общих обстоятельствах. –

+1

Вы можете * технически * добавить метод, чтобы использовать его в результате 'querySelectorAll', но это дорога, чреватая опасностью. 'NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;' –

ответ

10

JavaScript имеет первоклассные функции; то есть они рассматриваются как объекты и могут иметь свои собственные свойства и методы. Встроенный метод Function.call принимает параметр this для функции в качестве своего первого аргумента, а остальные аргументы передаются самой функции. Массив [] не используется, кроме как средство доступа к (менее сжатому, поэтому менее используемому) методу Array.prototype.forEach.

Это в основном восстановление Array.forEach для использования на чем-то, что не является массивом, в данном случае NodeList. Если NodeList s предложен метод forEach, то это было бы эквивалентно, и вы можете прочитать его как это:

document.querySelectorAll('input[type="checkbox"]').forEach(function(el) { 
    el.checked = true; 
});​ 

Так, чуть больше в глубину. call выполняет функцию с другим контекстом. forEach выполняет итерацию по контексту и вызывает функцию, которая передается в качестве аргумента. Таким образом, someFunc.call(thisArg, otherArg) будет выполнен, как если бы он был в контексте thisArg, например thisArg.someFunc(otherArg). Вот простейший пример:

function callMe(something) { 
    return something + this; 
} 

callMe('Hello'); // Hellonull or Hello[object Window] or something 
callMe.call({}, 'World'); // World[object Object] 

apply() работает точно так же, но передать массив аргументов в качестве второго аргумента.

+0

Подождите, что? Так что это 'NodeList' вместо' Array'? Разве «NodeList' * не является« массивом »? –

+2

Нет, 'NodeList' не * a * Array'. Однако, в принципе, он ведет себя как «Array» - он имеет числовые индексы и свойство 'length'. Он просто не наследует стандартные методы «Array». Однако, если 'method' нуждается только в индексировании и' length', это сработает, поэтому этот конкретный фрагмент кода действителен. –

+0

@TikhonJelvis - Итак, это «Массив» без методов, которые должен иметь «Массив». Понимаю. –

3

Обратите внимание: .call. Он применяет (устанавливает в) результаты document.querySelectorAll в forEach, так что он выполняет итерацию по этим результатам, а не (пустой) массив в левой части точки.

4

Это просто используется [], чтобы получить функцию forEach. Как только он имеет функцию, он использует .call, чтобы назвать его, как если бы это был метод document.querySelectorAll('input[type="checkbox"]').

Это полезно, потому что результат document.querySelectorAll не является Array, но ведет себя как один, поэтому мы можем использовать стандартные методы Array.

Когда вы используете .call, первый аргумент используется как значение this. То есть в этом конкретном фрагменте каждый раз, когда this встречается внутри источника forEach, он установлен в document.querySelectorAll('input[type="checkbox"]').

Вы не можете просто позвонить document.querySelectorAll('input[type="checkbox"]').forEach(... напрямую, потому что querySelectorAll делает не возвращать Array объект и поэтому не имеет методы forEach.Вся вещь .call - это всего лишь способ обойти это, позвонив forEachкак будто это был метод NodeList, который является тем, что действительно возвращается.