Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   почему вместо методов Array используют циклы (https://javascript.ru/forum/misc/43919-pochemu-vmesto-metodov-array-ispolzuyut-cikly.html)

finestra 26.12.2013 15:20

почему вместо методов Array используют циклы
 
постоянно вижу как для перебора массива используют циклы,
хотя такие методы как: forEach, reduce и т.д.,
по моему мнению, использовать гораздо удобней.
так почему же их игнорируют?

рони 26.12.2013 15:24

finestra,
если ненужна поддержка старых браузеров
http://kangax.github.io/es5-compat-t...totype.forEach

ksa 26.12.2013 22:05

Цитата:

Сообщение от finestra
по моему мнению, использовать гораздо удобней

А чем циклы-то провинились? :D

Vlasenko Fedor 26.12.2013 22:14

Потому, что можно искать быстрее
http://javascript.ru/forum/misc/4383...jj-cikl-5.html

danik.js 26.12.2013 23:10

Почему же. В тех же расширениях к браузерам можно запросто использовать эти методы. Или в коде для NodeJS. Ну и вобще, когда поддержка IE8 и других старых браузеров не нужна. Ну а если хочется, но нужна полная поддержка, то es5shim.js в помощь.

Antonius 27.12.2013 02:54

Почему-то был уверен, что forEach работает ощутимо медленнее за счет необходимости вызова функции на каждой итерации. Замерил (только в фаерфоксе). Удивился, но это не так.

То есть цикл с действиями, выполняемыми инлайново, отрабатывает медленнее, чем forEach с вызовом функции (с теми же действиями) на каждый элемент массива.

Похоже, что если нет проблем с поддержкой, то стоит отдавать предпочтение итерирующим методам.

cyber 27.12.2013 03:33

Antonius, http://jsperf.com/for-vs-foreach/111

Antonius 27.12.2013 03:42

Ага, любопытно. Сам тест у меня практически такой же, рассуждения верны, получается, а результаты неверны. Замерял в фаербаге console.time/timeEnd.

Да, итерирующие методы работают медленно. Печаль, ибо код с ними гораздо опрятнее.

cyber 27.12.2013 05:38

Antonius, по сути можно использовать forEach там где не критична производительность, и forEach не всегда медлнее.

Цитата:

Сообщение от Antonius
Замерял в фаербаге console.time/timeEnd.

Нужно замерять не один раз, а много и выводить среднее значение по времени, и нагружать как можно больше, вот к примеру асинхронный тест который не вешает браузер и синхронный (браузер подвисает) http://jsfiddle.net/2pZ3T/1/

<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>

Antonius 27.12.2013 05:49

А есть какое-то общее правило, которое может помочь определить, когда forEach не будет сильно уступать циклу?

Я для себя пока склоняюсь к подходу «использовать forEach тогда, когда внутри цикла мы делали бы вызов функции»

Aetae 27.12.2013 07:51

Используй forEach и проч. когда удобно. Если производительность упрётся именно в этом месте - всегда можно будет переписать циклом. Но скорее всего этого никогда не понадобится.)

danik.js 27.12.2013 08:32

Antonius, если писать код руководствуясь только скоростью работы, то получится трудно-поддерживаемая груда кода. Кроме того, разные варианты отрабатывают в разных браузерах по-разному, или даже в разных версиях одного браузера.

Antonius 27.12.2013 08:45

Цитата:

Сообщение от danik.js (Сообщение 289534)
Antonius, если писать код руководствуясь только скоростью работы, то получится трудно-поддерживаемая груда кода. Кроме того, разные варианты отрабатывают в разных браузерах по-разному, или даже в разных версиях одного браузера.

Да, приходится постоянно балансировать между читаемостью/поддерживаемостью и скоростью.

Однако в браузерах, доступных мне (okouser, это последние версии) тест http://jsperf.com/for-vs-foreach/111 показывает проигрыш forEach, в разной степени, иногда с небольшой разницей, иногда с внушительной, но он медленнее.

Кстати, да, еще можно руководствоваться такими соображениями — если действия, выполняемые в каждой итерации цикла, достаточно «дорогие» по производительности, то накладные расходы на организацию самого обхода массива существенного влияния на время выполнения не окажут.

cyber 27.12.2013 15:27

okouser, по сути если нужно обработать массив на пару тысяч элементов то лучше использовать for (что вообще не является хорошо:)), а так разница в пару милесекунд http://jsfiddle.net/eT25E/

kobezzza 27.12.2013 16:00

Я в своё время заморочился, и написал свою реализацию forEach с JIT компиляцией, по скорости равна циклам.

cyber 27.12.2013 17:19

kobezzza, поделишься?)

Antonius 27.12.2013 17:30

Цитата:

Сообщение от kobezzza (Сообщение 289594)
Я в своё время заморочился, и написал свою реализацию forEach с JIT компиляцией, по скорости равна циклам.

Откройте секрет, как можно со стороны скрипта влиять на JIT?

kobezzza 27.12.2013 18:18

Цитата:

Сообщение от cyber (Сообщение 289612)
kobezzza, поделишься?)

Как закончу работу над Snakeskin, то опубликую (там кое что допилить надо ещё и тестов понаписать).

kobezzza 27.12.2013 18:24

Цитата:

Сообщение от Antonius (Сообщение 289613)
Откройте секрет, как можно со стороны скрипта влиять на JIT?

Я написал свой, он производит инлайнинг, декомпозицию, дополнительные кеширования и т.д. что в итоге позволяет нативному JIT максимально эффективно обрабатывать такие конструкции, в январе планирую описать в подробной статье, т.к. штука интересная оч получилась.

Antonius 27.12.2013 22:37

Ждем января, значит :) Не пропустить бы.

cyber 23.01.2014 20:05

Цитата:

Сообщение от kobezzza
Я написал свой, он производит инлайнинг, декомпозицию, дополнительные кеширования и т.д. что в итоге позволяет нативному JIT максимально эффективно обрабатывать такие конструкции, в январе планирую описать в подробной статье, т.к. штука интересная оч получилась.

Ты еще не забыл про статью, интересно всетаки ?:)

kobezzza 26.01.2014 12:11

Цитата:

Сообщение от cyber (Сообщение 293680)
Ты еще не забыл про статью, интересно всетаки ?:)

Месяц ещё не закончен:) прост стараюсь работать по плану, со след недели приступаю к написанию статьи и релизу.

melky 26.01.2014 14:56

Цитата:

Сообщение от kobezzza (Сообщение 294136)
Месяц ещё не закончен:) прост стараюсь работать по плану, со след недели приступаю к написанию статьи и релизу.

хм. с помощью этой штуки можно такие вещи вытворять ... если будет хорошо спроектирована

было бы круто вкушать все прелести ФП с компиляцией в JS без потери производительности на функции.

т.е. :
ФП -> ИП, развороты рекурсий и т.д.

cyber 27.01.2014 19:14

Цитата:

Сообщение от kobezzza
Месяц ещё не закончен прост стараюсь работать по плану, со след недели приступаю к написанию статьи и релизу.

ждемс)

kobezzza 29.01.2014 15:35

Цитата:

Сообщение от cyber (Сообщение 294422)
ждемс)

Планирую в эту субботу/воскресение закончить.

cyber 29.01.2014 15:41

Цитата:

Сообщение от kobezzza
Планирую в эту субботу/воскресение закончить.

где смотреть? Хабр? гитхаб? или на форуме в оффтопе ссылку кинешь?

kobezzza 29.01.2014 15:46

Цитата:

Сообщение от cyber (Сообщение 294739)
где смотреть? Хабр? гитхаб? или на форуме в оффтопе ссылку кинешь?

тут на форуме кину ссылку на гитхаб)

kobezzza 02.02.2014 14:44

http://javascript.ru/forum/showthrea...370#post295370
https://github.com/kobezzza/Collection

kostyanet 03.02.2014 10:19

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.

kostyanet 03.02.2014 10:25

Короткий ответ на вопрос темы: потому что массивы в js - угребище. Это называется ни вашим, ни нашим. Массивы не нормальные, то есть не массивы вовсе, но и не map (и значит не balanced tree). Вследствие чего народ юзает "объекты" в качестве map (dictionary канонично), а там без всяких форичей for in предусмотрен.


Часовой пояс GMT +3, время: 07:49.