[]
это массив.
Этот массив вообще не используется.
Он размещается на странице, потому что использование массива дает вам доступ к прототипам массива, например .forEach
.
Это быстрее, чем печатать Array.prototype.forEach.call(...);
Далее forEach
идет функция, которая принимает на вход функцию ...
[1,2,3].forEach(function (num) { console.log(num); });
... и для каждого элемента в this
(где this
подобен массиву, поскольку у него есть, length
и вы можете получить доступ к его частям, например this[1]
), он передаст три вещи:
- элемент в массиве
- индекс элемента (третий элемент пройдет
2
)
- ссылка на массив
Наконец, .call
это прототип, который есть у функций (это функция, которая вызывается для других функций).
.call
примет свой первый аргумент и заменит this
внутри обычной функции все, что вы передали call
в качестве первого аргумента ( undefined
или null
будет использовать window
в повседневном JS, или будет тем, что вы передали, если в "строгом режиме"). Остальные аргументы будут переданы исходной функции.
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
Таким образом, вы создаете быстрый способ вызова forEach
функции и переходите this
от пустого массива к списку всех <a>
тегов, и для каждого <a>
по порядку вы вызываете предоставленную функцию.
РЕДАКТИРОВАТЬ
Логический вывод / Очистка
Ниже приводится ссылка на статью, в которой предлагается отказаться от попыток функционального программирования и каждый раз придерживаться ручного встроенного цикла, потому что это решение взломано и некрасиво.
Я бы сказал , что в то время как .forEach
менее полезны , чем его коллеги, .map(transformer)
, .filter(predicate)
, .reduce(combiner, initialValue)
, он по- прежнему служит целям , когда все , что вам действительно нужно сделать , это изменить внешний мир ( а не массив), N-раз, в то время как имеющие доступ к любой arr[i]
или i
.
Итак, как нам справиться с неравенством, ведь Девиз явно талантливый и знающий парень, и я хотел бы представить, что я знаю, что делаю / куда иду (время от времени ... ... другое раз это обучение с головы до ног)?
Ответ на самом деле довольно прост, и что-то, что дядя Боб и сэр Крокфорд могли бы потерять лицо из-за недосмотра:
убери это .
function toArray (arrLike) { // or asArray(), or array(), or *whatever*
return [].slice.call(arrLike);
}
var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);
Теперь, если вы сомневаетесь, нужно ли вам это делать самому, ответ вполне может быть отрицательным ...
В наши дни именно это делается ... ... каждой (?) Библиотекой с функциями высшего порядка.
Если вы используете lodash, подчеркивание или даже jQuery, у всех них будет способ взять набор элементов и выполнить действие n раз.
Если вы не используете такую вещь, то непременно напишите свою.
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);
};
Обновление для ES6 (ES2015) и последующих версий
Вспомогательный метод slice( )
/ array( )
/ etc не только упростит жизнь людям, которые хотят использовать списки точно так же, как они используют массивы (как они должны), но и тем людям, которые могут позволить себе роскошь работать в браузерах ES6 + относительно близких future, или «транспиляции» в Babel сегодня, у вас есть встроенные языковые функции, которые делают подобные вещи ненужными.
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 ];
Супер-чисто и очень полезно.
Найдите операторы Rest и Spread ; опробуйте их на сайте BabelJS; если ваш стек технологий в порядке, используйте их в производстве с помощью Babel и этапа сборки.
Нет веской причины не использовать преобразование из не массива в массив ... ... просто не путайте свой код, ничего не делая, кроме вставки той же уродливой строки повсюду.
.call
это изменить значениеthis
, поэтому вы используетеcall
с Foreach. Если forEach выглядит так,forEach (fn) { var i = 0; var len = this.length; for (; i < length; i += 1) { fn( this[i], i, this ); }
то изменение сthis
помощью словаforEach.call( newArrLike )
означает, что он будет использовать этот новый объект какthis
..call
не изменяет значениеthis
внутри того, что вы передаетеforEach
,.call
изменяет значениеthis
внутри forEach . Если выthis
не понимаете, почему не передаетсяforEach
функция, которую вы хотели вызвать , вам следует проверить поведениеthis
в JavaScript. В качестве дополнения, применимого только здесь (и map / filter / reduce), есть второй аргументforEach
, который устанавливаетсяthis
внутри функцииarr.forEach(fn, thisInFn)
или[].forEach.call(arrLike, fn, thisInFn);
или просто use.bind
;arr.forEach(fn.bind(thisInFn));
[]
существует просто как массив, так что вы можете.call
использовать.forEach
метод и изменитьthis
его на набор, над которым хотите работать..call
выглядит следующим образом : заfunction (thisArg, a, b, c) { var method = this; method(a, b, c); }
исключением того, что есть внутренняя черная магия , чтобы установитьthis
внутриmethod
равные , что вы прошли , какthisArg
.querySelectorAll
метод возвращаетNodeList
, который похож на массив, но это не совсем массив. Следовательно, у него нетforEach
метода (через который наследуются объекты массиваArray.prototype
).Поскольку a
NodeList
похож на массив, методы массива фактически будут работать с ним, поэтому, используя,[].forEach.call
вы вызываетеArray.prototype.forEach
метод в контекстеNodeList
, как если бы вы могли просто сделатьyourNodeList.forEach(/*...*/)
.Обратите внимание, что литерал пустого массива - это просто ярлык для расширенной версии, которую вы, вероятно, тоже будете видеть довольно часто:
источник
[].forEach.call(['a','b'], cb)
over['a','b'].forEach(cb)
в повседневных приложениях со стандартными массивами, просто при попытке перебора структур, подобных массиву, которые не имеютforEach
собственного прототипа? Это правильно?[].forEach()
:)var section = document.querySelectorAll(".section"); section.forEach((item)=>{ console.log(item.offsetTop) })
работает хорошоforEach
массивов, но не Nodelist объекты)Другие ответы очень хорошо объяснили этот код, поэтому я просто добавлю предложение.
Это хороший пример кода, который следует отремонтировать для простоты и ясности. Вместо использования
[].forEach.call()
orArray.prototype.forEach.call()
каждый раз, когда вы это делаете, сделайте из него простую функцию:Теперь вы можете вызывать эту функцию вместо более сложного и непонятного кода:
источник
Лучше написать, используя
Это
document.querySelectorAll('a')
возвращает объект, похожий на массив, но не наследующий отArray
типа. Поэтому мы вызываемforEach
метод изArray.prototype
объекта с контекстом в качестве значения, возвращаемогоdocument.querySelectorAll('a')
источник
Это в основном то же самое, что:
источник
Хотите обновить этот старый вопрос:
Причина использования
[].foreach.call()
циклического перебора элементов в современных браузерах в основном исчезла. Мы можем использоватьdocument.querySelectorAll("a").foreach()
напрямую.источник
Пустой массив имеет свойство
forEach
в своем прототипе, которое является объектом Function. (Пустой массив - это просто простой способ получить ссылку наforEach
функцию, которая есть у всехArray
объектов.) Функциональные объекты, в свою очередь, имеютcall
свойство, которое также является функцией. Когда вы вызываете функциюcall
функции, она запускает функцию с заданными аргументами. Первый аргумент делаетсяthis
в вызываемой функции.Вы можете найти документацию по этой
call
функции здесь . ДокументацияforEach
находится здесь .источник
Просто добавьте одну строчку:
И вуаля!
Наслаждаться :-)
Предупреждение: NodeList - это глобальный класс. Не используйте эту рекомендацию, если вы пишете для публичной библиотеки. Однако это очень удобный способ повысить самоэффективность при работе на веб-сайте или в приложении node.js.
источник
Просто быстрое и грязное решение, которое я всегда использую. Я бы не стал трогать прототипы, это было хорошей практикой. Конечно, есть много способов сделать это лучше, но идею вы поняли.
источник
[]
всегда возвращает новый массив, он эквивалентен,new Array()
но гарантированно возвращает массив, потому что онArray
может быть перезаписан пользователем, тогда как[]
не может. Таким образом, это безопасный способ получить прототип, которыйArray
, как описано,call
используется для выполнения функции в массиве узлов (this).источник
[]
на самом деле всегда будет возвращать массив, в то время какwindow.Array
его можно перезаписать чем угодно (во всех старых браузерах), поэтому также можноwindow.Array.prototype.forEach
перезаписать чем угодно. В любом случае нет гарантии безопасности в браузерах, которые не поддерживают геттеры / сеттеры или запечатывание / замораживание объектов (замораживание вызывает собственные проблемы с расширяемостью).prototype
или это методы:forEach
.Норгуард объяснил, ЧТО
[].forEach.call()
делает, и Джеймс Аллардис, ПОЧЕМУ мы это делаем: потому что querySelectorAll возвращает объектNodeList
, у которого нет метода forEach ...Если у вас нет современного браузера, такого как Chrome 51+, Firefox 50+, Opera 38, Safari 10.
Если нет, вы можете добавить полифилл :
источник
На этой странице много полезной информации (см. Ответ + ответ + комментарий ), но недавно у меня был тот же вопрос, что и у OP, и потребовалось немного покопаться, чтобы получить полную картину. Итак, вот краткая версия:
Цель состоит в том, чтобы использовать
Array
методы в массиве,NodeList
который сам не имеет этих методов.В более старом шаблоне методы Array
Function.call()
использовались с помощью литерала массива ([]
), а неArray.prototype
потому, что он был короче для ввода:Более новый шаблон (после ECMAScript 2015) должен использовать
Array.from()
:источник