почему вместо методов Array используют циклы
постоянно вижу как для перебора массива используют циклы,
хотя такие методы как: forEach, reduce и т.д., по моему мнению, использовать гораздо удобней. так почему же их игнорируют? |
finestra,
если ненужна поддержка старых браузеров http://kangax.github.io/es5-compat-t...totype.forEach |
Цитата:
|
Потому, что можно искать быстрее
http://javascript.ru/forum/misc/4383...jj-cikl-5.html |
Почему же. В тех же расширениях к браузерам можно запросто использовать эти методы. Или в коде для NodeJS. Ну и вобще, когда поддержка IE8 и других старых браузеров не нужна. Ну а если хочется, но нужна полная поддержка, то es5shim.js в помощь.
|
Почему-то был уверен, что forEach работает ощутимо медленнее за счет необходимости вызова функции на каждой итерации. Замерил (только в фаерфоксе). Удивился, но это не так.
То есть цикл с действиями, выполняемыми инлайново, отрабатывает медленнее, чем forEach с вызовом функции (с теми же действиями) на каждый элемент массива. Похоже, что если нет проблем с поддержкой, то стоит отдавать предпочтение итерирующим методам. |
Antonius, http://jsperf.com/for-vs-foreach/111
|
Ага, любопытно. Сам тест у меня практически такой же, рассуждения верны, получается, а результаты неверны. Замерял в фаербаге console.time/timeEnd.
Да, итерирующие методы работают медленно. Печаль, ибо код с ними гораздо опрятнее. |
Antonius, по сути можно использовать forEach там где не критична производительность, и forEach не всегда медлнее.
Цитата:
<input id="start" type="button" value="start test" > <script> var divs = []; function domGenerate() { var container = document.createDocumentFragment(); for(var i = 0; i < 1000; i++) { var div = document.createElement("div"); div.innerHTML = i; divs.push(div); container.appendChild(div); } document.body.appendChild(container); } domGenerate(); function domClearFor() { for(var i = 0; i < divs.length; i++) divs[i].parentNode.removeChild(divs[i]); divs = []; domGenerate(); } function domClearForEach() { divs.forEach(function (item) { item.parentNode.removeChild(item); }); divs = []; domGenerate(); } function test(fnc, count, callback) { var time = 0, i = 0, d; (function runTest() { if(i++ == count) { callback(time / count); return; } d = new Date; fnc(); time += new Date - d; setTimeout(runTest, 0); }()); } function testSync(fnc, count, callback) { var time = 0, d; for(var i = 0; i < count; i++){ d = new Date; fnc(); time += new Date - d; } callback && callback(time / count); return time / count; }; document.getElementById("start").onclick = function () { console.log("test running..."); this.value = "test running..."; test(domClearFor, 1000, function (time) {// асинхронный test console.log("for", time); }); test(domClearForEach, 1000, function (time) { console.log("forEach", time); }); }; </script> |
А есть какое-то общее правило, которое может помочь определить, когда forEach не будет сильно уступать циклу?
Я для себя пока склоняюсь к подходу «использовать forEach тогда, когда внутри цикла мы делали бы вызов функции» |
Используй forEach и проч. когда удобно. Если производительность упрётся именно в этом месте - всегда можно будет переписать циклом. Но скорее всего этого никогда не понадобится.)
|
Antonius, если писать код руководствуясь только скоростью работы, то получится трудно-поддерживаемая груда кода. Кроме того, разные варианты отрабатывают в разных браузерах по-разному, или даже в разных версиях одного браузера.
|
Цитата:
Однако в браузерах, доступных мне (okouser, это последние версии) тест http://jsperf.com/for-vs-foreach/111 показывает проигрыш forEach, в разной степени, иногда с небольшой разницей, иногда с внушительной, но он медленнее. Кстати, да, еще можно руководствоваться такими соображениями — если действия, выполняемые в каждой итерации цикла, достаточно «дорогие» по производительности, то накладные расходы на организацию самого обхода массива существенного влияния на время выполнения не окажут. |
okouser, по сути если нужно обработать массив на пару тысяч элементов то лучше использовать for (что вообще не является хорошо:)), а так разница в пару милесекунд http://jsfiddle.net/eT25E/
|
Я в своё время заморочился, и написал свою реализацию forEach с JIT компиляцией, по скорости равна циклам.
|
kobezzza, поделишься?)
|
Цитата:
|
Цитата:
|
Цитата:
|
Ждем января, значит :) Не пропустить бы.
|
Цитата:
|
Цитата:
|
Цитата:
было бы круто вкушать все прелести ФП с компиляцией в JS без потери производительности на функции. т.е. : ФП -> ИП, развороты рекурсий и т.д. |
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
|
forEach выполняет те же циклы но за вас требуя от вас колбэка.
https://developer.mozilla.org/en-US/.../Array/forEach С той разницей что недействительных членов вы не увидите: var t = Object(this); ... if (i in t) fun.call(thisArg, t[i], i, t); То есть var arr=[]; arr[1] = 1; arr[10] = 10; console.log(arr.length); // 11 а forEach() выдаст ровно 2. Типо там map. |
Короткий ответ на вопрос темы: потому что массивы в js - угребище. Это называется ни вашим, ни нашим. Массивы не нормальные, то есть не массивы вовсе, но и не map (и значит не balanced tree). Вследствие чего народ юзает "объекты" в качестве map (dictionary канонично), а там без всяких форичей for in предусмотрен.
|
Часовой пояс GMT +3, время: 07:49. |