Перебір властивостей об'єктах. JQuery - Перебір масиву, об'єкта та елементів Явне використання ітератора
Це працює так:
// REQUIRES ECMASCRIPT 2015+ var s, myStringArray = ["Hello", "World"]; for (s of myStringArray) ( // ... do something with s ... )
Або ще краще, оскільки ECMAScript 2015 також надає змінні в області блоку за допомогою let і const:
// REQUIRES ECMASCRIPT 2015+ const myStringArray = ["Hello", "World"]; for (const s of myStringArray) ( // ... do something with s ... ) // s is no longer defined here
Примітка про розріджені масиви: масив JavaScript може фактично не зберігати стільки елементів, скільки зазначено в його length ; це повідомлення просто на одиницю більше, ніж найвищий індекс, при якому зберігається значення. Якщо масив містить менше елементів, ніж зазначено у його довжині, він називається розрідженим. Наприклад, цілком законно мати масив з елементами лише за індексами 3, 12 та 247; length такого масиву вказана як 248, хоча насправді він зберігає лише 3 значення. Якщо ви спробуєте отримати доступ до елемента за будь-яким іншим індексом, у масиву з'явиться undefined значення. Тому, коли ви хочете "перебрати" масив, у вас є питання, на яке потрібно відповісти: чи ви хочете перебрати весь діапазон, вказаний його довжиною, і обробити undefined для будь-яких пропущених елементів, або ви хочете обробити тільки елементи насправді подарунок? Існує безліч програм для обох підходів; це залежить тільки від того, навіщо ви використовуєте масив.
Якщо ви перебираєте масив за допомогою for .. of , тіло циклу виконується по length , а змінна керування циклом встановлюється undefined для будь-яких елементів, які насправді відсутні у масиві. Залежно від деталей вашого коду "що робити", така поведінка може бути тим, що ви хочете, але якщо це не те, що ви хочете, вам слід використовувати інший підхід.
Звичайно, деякі розробники не мають іншого вибору, крім використання іншого підходу в будь-якому випадку, тому що з якоїсь причини вони орієнтації версію JavaScript, який ще не підтримується for ... of .
Поки ваша реалізація JavaScript є сумісною з попередньою версією специфікації ECMAScript (яка, наприклад, виключає версії Internet Explorer до 9), ви можете використовувати метод ітератора Array#forEach замість циклу. У цьому випадку ви передаєте функцію, яка буде викликатись для кожного елемента в масиві:
Var myStringArray = ["Hello", "World"]; myStringArray.forEach(function(s) ( // ... do something with s ... ));
На відміну від for ... of , .forEach викликає функцію лише елементів, які насправді містять значення. Якщо передати наш гіпотетичний масив з трьома елементами та довжиною 248, він буде викликати функцію лише три рази, а не 248 разів. Він також розрізняє відсутні елементи та елементи, які насправді встановлені як undefined; Для останнього він як і раніше буде викликати функцію, передаючи як аргумент undefined значення. Якщо це, як ви хочете обробляти розріджені масиви, .forEach може бути шлях, навіть якщо ваш перекладач підтримує for ... of .
Останній варіант, який працює у всіх версіях JavaScript, – це явний цикл підрахунку. Ви просто вважаєте від 0 до одиниці менше довжини і використовуєте лічильник як індекс. Основний цикл виглядає так:
Однією з переваг цього підходу є те, що ви можете вибирати, як обробляти розріджені масиви; Наведений вище код буде запускати тіло циклу на повний length з s встановленим на undefined для будь-яких відсутніх елементів, як for .. of . Якщо замість цього ви хочете обробляти тільки реально існуючі елементи розрідженого масиву, такі як .forEach, ви можете додати in індекс просту перевірку: Var i, s, myStringArray = ["Hello", "World"], len = myStringArray.length; for (i=0; i Присвоєння значення довжини локальної змінної (на відміну включення повного висловлювання myStringArray.length за умов циклу) може істотно myStringArray.length на продуктивність, оскільки воно пропускає пошук властивостей щоразу остаточно; при використанні Rhino на моїй машині прискорення становить 43%. Ви можете побачити, що кешування довжини виконується у пропозиції ініціалізації циклу, наприклад: Var i, len, myStringArray = ["Hello", "World"]; for (len = myStringArray.length, i = 0; i Згаданий іншими синтаксис for...in використовується для циклічного обходу властивостей об'єкта; Так як масив в JavaScript - це просто об'єкт з числовими іменами властивостей (і властивістю length, що автоматично оновлюється), ви можете теоретично зациклити масив з ним. Але проблема полягає в тому, що він не обмежується числовими значеннями властивостей (пам'ятаєте, що навіть методи насправді просто властивості, значення яких є замиканням), і при цьому не гарантується, що вони будуть повторюватися в числовому порядку. Отже, синтаксис for ... in не повинен використовуватися для циклічного переміщення масивами. Вітаю! Продовжуємо вивчати методи масивів і у цьому уроці розглянемо методи для перебору масиву. Ці методи дозволяють пройтися масивом і виконати певні дії над його елементами. Так забув сказати всі ці методи не підтримуються в IE 8. Хоча так це вже зараз важливо що вони не підтримуються цим браузером, але все ж якщо хочете підтримку IE8, то ES5-shim вам в допомогу. А ми продовжуватимемо Даний метод використовується для проходу масивом в циклі, але йому можна передати функцію, в якій можна робити певні дії над елементами масиву. Розглянемо з прикладу. Var mas = ["Банан", "Авокадо", "Морква"]; mas.forEach(function(item, i, mas) ( alert(i + ": " + item + " (масив:" + mas + ")"); )); Тут у прикладі в метод forEach передається функція в якій вказується 3 параметри: item- Елемент масиву i- Номер елементу масиву mas- Масив, який обробляється. Даний метод можна використовувати замість циклу для перебору масиву. Цей метод також як і метод forEach використовується для перебору масиву і йому передається функція як аргумент, але він дозволяє фільтрувати масив і повертає новий масив, куди потрапляють лише ті елементи для яких функція, яку ми передаємо в цей метод, поверне true. Трохи заплутано, тож розглянемо на прикладі. Var mas =; var positiveNum = mas.filter(function(num) ( return num > 0; )); document.write(positiveNum); // 1,4,3 У прикладі є масив із числами і нам треба отримати інший масив, в якому були б лише позитивні числа з вихідного масиву. Для цього до масиву застосовуємо метод filter і викликаємо функцію, яка перевірятиме кожен елемент, тобто вона поверне всі позитивні числа, а результат буде зберігатися в іншому масиві в прикладі це positiveNum. Метод map створює інший масив, який буде складатися з результатів виклику функції вихідного масиву, але в цій функції над елементами вихідного масиву відбуватимуться якісь дії і результат виявиться в новому масиві як. Давайте розберемо приклад, бо я думаю зовсім незрозуміло. Var mas =; var newMas = mas.map(function(item) ( return item*item; )); // отримали масив із квадратами alert(newMas); // 1,4,9 У прикладі є вихідний масив з числами до нього застосовується метод map, в якому кожен елемент масиву множиться сам на себе і результат записується в інший масив. У результаті отримаємо масив із квадратами чисел вихідного масиву. Дані методи перевіряють присутній елемент у масиві. Роблять вони це через функцію, яка їм передається як параметр, тобто якщо ця функція поверне true, тоді і сам метод поверне true. Причому метод every вимагає, щоб кожен елемент відповідав умові функції, а метод some, щоб хоча б один відповідав. І як завжди ось вам приклад. Var mas =; function isPositiv(num) ( return num > 0; ) if(mas.every(isPositiv)) ( document.write("Масив містить тільки позитивні числа"); ) else( document.write("У масиві є хоча б одне негативне число "); ) if(mas.some(isPositiv)) ( document.write("У масиві є хоча б одне позитивне число"); ) else ( document.write("У масиві немає позитивних чисел"); ) Розглянемо приклад у нас є масив із позитивними та негативними числами і нам треба перевірити його на наявність хоча б одного негативного числа. Для цього використовуємо методи every та some. Створюємо функцію, яка повертатиме позитивні числа і потім її передаємо в метод every оскільки даний метод повертає логічний результат, то використовується він в умовних операторах. Метод every у нашому прикладі поверне false тому що в масиві є негативні числа, а ось метод some поверне true, тому що в масиві є хоча б одне позитивне число. Якщо вам потрібно перебрати масив – ви можете використовувати forEach, for або for..of. Якщо вам потрібно перебрати масив і повернути дані для кожного елемента, ви використовуєте map. Методи arr.reduceі arr.reduceRightсхожі на методи вищі, але вони трішки складніші. Вони використовуються для обчислення якогось одного значення на основі всього масиву. Синтаксис: Let value = arr.reduce(function(previousValue, item, index, array) ( // ... ), ); Функція застосовується по черзі до всіх елементів масиву і переносить свій результат на наступний виклик. Аргументи: При виклику функції результат її виклику попередньому елементі масиву передається як аргумент. Звучить складно, але все стає простіше, якщо думати про перший аргумент як результат, що «акумулює» попередніх викликів функції. Після закінчення він стає результатом зменшення. Цей метод найпростіше зрозуміти як завжди на прикладі. Тут ми отримаємо суму всіх елементів масиву лише одним рядком: Let arr =; let result = arr.reduce((sum, current) => sum + current, 0); alert(result); // 15 Тут ми використовували найпоширеніший варіант reduce, який використовує лише 2 аргументи. Давайте детальніше розберемо, як він працює. Потік обчислень виходить такий: У вигляді таблиці, де кожен рядок – виклик функції на черговому елементі масиву: Тут виразно видно, як результат попереднього виклику передається до першого аргументу наступного. Ми також можемо опустити початкове значення: Let arr =; // прибрано початкове значення (немає 0 наприкінці) let result = arr.reduce((sum, current) => sum + current); alert(result); // 15 Результат – такий самий! Це тому, що за відсутності initial як одне значення береться перший елемент масиву, а перебір стартує з другого. Таблиця обчислень буде такою самою за вирахуванням першого рядка. Але таке використання потребує надзвичайної обережності. Якщо масив є порожнім, то виклик reduce без початкового значення видасть помилку. Ось приклад: Let arr =; // Error: Reduce of empty array with no initial value // Якби існувало початкове значення, reduce повернув його для порожнього масиву. arr.reduce((sum, current) => sum + current); Отже підіб'ємо підсумки ми розглянули різні методи для роботи з масивами в циклі у всіх цих методів є одне спільне те, що всім їм треба передавати функцію в якості аргументу. Нехай даний масив var mas = ["HTML", "CSS", "JavaScript", "Pascal"] вам треба за допомогою методу map отримати новий масив, який буде містити довжини кожного елемента вихідного масиву. Є масив var mas = вам потрібно, використовуючи метод filter отримати масив, який містить лише позитивні числа. Є масив var mas = вам треба перевірити, чи є в масиві негативні числа і вивести результат на екран. Ну і на завершення невелике відео за методами для перебору масиву в циклі.
Приклад використання: До переваг дляEach відноситься те, що тут не потрібно оголошувати локальні змінні для зберігання індексу та значення поточного елемента масиву, оскільки вони автоматично передаються у функцію зворотного виклику (колбек) як аргументи. Якщо вас турбують можливі витрати на виклик колбека для кожного елемента, не хвилюйтеся та прочитайте це. ForEach призначений для перебору всіх елементів масиву, але крім нього ES5 пропонує ще кілька корисних методів для перебору всіх або деяких елементів плюс виконання при цьому будь-яких дій з ними: Var a = ["a", "b", "c"]; var index; for (index = 0; index< a.length; ++index) {
console.log(a);
}
Var a = ["a", "b", "c"]; var index, len; for (index = 0, len = a.length; index< len; ++index) {
console.log(a);
}
Якщо порядок перебору елементів не важливий, то можна піти ще далі в плані оптимізації та позбутися змінної для зберігання довжини масиву, змінивши порядок перебору на зворотний: Var a = ["a", "b", "c"]; var index; for (index = a.length - 1; index >= 0; --index) ( console.log(a); ) Тим не менш, у деяких випадках, таких як перебір розріджених масивів , for ... in може виявитися корисним, якщо тільки дотримуватися при цьому запобіжних заходів, як показано в прикладі нижче: // a - розріджений масив var a =; a = "a"; a = "b"; a = "c"; for (var key in a) ( if (a.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && key<= 4294967294) {
console.log(a);
}
}
Щоб не писати такий громіздкий код перевірок щоразу, коли потрібно перебір масиву, можна оформити його у вигляді окремої функції: Function arrayHasOwnIndex(array, key) ( return array.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && key<= 4294967294;
}
For (key in a) ( if (arrayHasOwnIndex(a, key))) ( console.log(a); ) ) For (key in a) ( if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) ( console.log(a); ) ) Ітератор
- це реалізований об'єктом протокол, який визначає стандартний спосіб отримання послідовності значень (кінцевої чи нескінченної). Приклад використання for...of: Var val; var a = ["a", "b", "c"]; for (val of a) (console.log(val); ) Var a = ["a", "b", "c"]; var it = a.entries(); var entry; while (!(entry = it.next()).done) ( console.log(entry.value); ) Конструкції for і for...in можуть бути застосовані до масивоподібних об'єктів точно тим самим шляхом, що і до масивів. ForEach та інші методи Array.prototype також застосовуються до масивоподібних об'єктів. Для цього потрібно використовувати виклик Function.call або Function.apply. Наприклад, якщо ви хочете застосувати forEach до властивості childNodes об'єкта Node , то це робиться так: Array.prototype.forEach.call(node.childNodes, function(child) ( // робимо що-небудь з об'єктом child)); // (передбачається, що весь код нижче знаходиться в одній області видимості) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // робимо що-небудь з об'єктом child)); Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0); Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0); 12 Бер 2016 У сучасному JavaScript існують, так звані методи, що «перебирають», які застосовуються для перебору масивів. У цьому уроці ми розглянемо такі методи: Метод.forEach() використовується для переборумасиву. Він викликає так звану функцію callback, за допомогою якої надається три параметри item, i, arr, де: Щоб простіше було зрозуміти, як використовувати цей метод, розглянемо приклад: Var user=["admin","pass",31]; user.forEach(function(item,i,user)( alert("Значення елемента за № " + i + " : " + item); )); Цей метод можна використовувати замість звичайного циклу for. Метод.filter() використовується для фільтрації, він також використовує функцію callback, але створює новий масив, якщо елементи в масиві підходять під значення true: Var arr =; var newArr=arr.filter(function(number)( return number< 0;
});
alert(newArr); // выведет -34,-4
У цьому прикладі перевіряються числа негативні значення, але в виході виводиться новий масив із цими значеннями. Ви можете вигадати свої умови, зовсім необов'язково це повинні бути числа. Ці два методи схожі один з одним і обидва використовуються для перевірки масиву, тільки метод .every()повертає значення true якщо всі значення масиві підходять під задану умову, а метод .some()повертає true якщо хоча б одне значення підходить під умову: Var arr =; alert(arr.every(function(number)( return number)< 0;
})); // выведет false
Сподіваюся зрозуміло, що якби у прикладі вище використовувався метод someто в нас вивелося б значення true, замість false. Метод.map() трансформує масив та отримує з нього новий. Все робиться за допомогою виклику callback-функції: Var arr =; var newArr=arr.map(function(number)( return number*2; )); alert(newArr); У цьому прикладі ми отримали новий масив із подвоєними значеннями елементів. Останні методи, які ми з вами розглянемо це reduce і reduceright. Використовуються для обробки кожного елемента масиву зі збереженням проміжного результату. Метод перебирає кожен елемент зліва направо, зменшуючиправоруч навпаки. На відміну від інших методів, крім функції callback, тут ще вказується аргумент initialValue — «початкове значення». Плюс до всього функції callback вказується «проміжний результат» - previousValueі currentItem- поточний елемент масиву. Давайте розглянемо приклад: Function getSums(arr) ( var result = ; if (!arr.length) return result; var totalSum = arr.reduceRight(function(sum, item) ( result.push(sum); return sum + item; )); .push(totalSum); return result; // 1,3,6,10,15 Що сталося у цьому прикладі? Ми створили функцію, яка дозволяє отримати новий масив із елементами, створеними із суми попередніх. Причому, звіт елементів йде з кінця. А ось більш простий приклад, в якому я створив функцію, що вважає суму елементів у масиві: Function getSum(arr) ( var result = arr.reduce(function(sum, current) ( return sum + current )); return result; ); alert(getSum()); Теги: 22 відповіді Після виконання цього тесту з більшістю сучасних браузерів... В даний часнайшвидша форма циклу (і, як на мене, найбільш синтаксично очевидна). стандарт для циклу з кешуванням за довжиною For (var i = 0, len = myArray.length; i< len; i++) {
}
Я б сказав, що це безперечно випадок, коли я вітаю розробників движка JavaScript. Час виконання має бути оптимізовано для ясності, а не для зручності.
Станом на червень 2016 року, кілька тестів в останньому Chrome (71% ринку браузерів у травні 2016 року та збільшення): Я вважаю, що цей потік занадто старий, і програмісти вважають, що їм потрібно кешувати довжину, або використовувати зворотні перетину зі зменшенням, щоб домогтися більшої продуктивності, написання коду, який є менш розбірливим і більш схильним до помилок, ніж простий для циклу. Тому я рекомендую: Якщо ваша програма повторює безліч елементів або ваш код циклу знаходиться всередині функції, яка використовується часто, прямий цикл є відповіддю: For (var i = 0; i< arr.length; i++) {
// Do stuff with arr[i] or i
} Якщо ваша програма дійсно не перебирає безліч елементів або вам просто потрібно робити невеликі ітерації тут і там, використання стандартного зворотного виклику forEach або будь-якої подібної функції з обраної вами бібліотеки JS може бути більш зрозумілим і менш схильний до помилок, оскільки область змінних індексу закрита, і вам не потрібно використовувати дужки, що безпосередньо звертаються до значення масиву: Arr.forEach(function(value, index) ( // Do stuff with value or index )); Якщо вам дійсно потрібно пом'яти кілька мілісекунд, ітерації по мільярдах рядків, і довжина масиву не зміниться в процесі, ви можете подумати про довжину кешування в циклі for. Хоча я думаю, що в наші дні це справді не потрібно: For (var i = 0, len = arr.length; i< len; i++) {
// Do stuff with arr[i]
}
Це просто 2018, так що оновлення може бути гарним... І я дійсно повинен не погодитися з прийнятою відповіддю. Це залежить від різних браузерів. деякі роблять forEach швидше, деякі for-loop , а деякі while тестують всі методи http://jsben.ch/mW36e Arr.forEach(a => ( // ... ) і так як ви можете побачити безліч циклів for(a = 0;...) наприклад, for(a = 0;...) то варто згадати, що без змінних "var" буде визначатися глобально, і це може суттєво вплинути на швидкість, тому вона буде повільною. var arr = arr = new Array(11111111).fill(255); var benches = [["empty", () =>< l; a++);
}]
, ["for-loop", () =>( for(var a = 0, l = arr.length; a< l; ++a)
var b = arr[a] + 1;
}]
, ["for-loop++", () =>( for(var a = 0, l = arr.length; a< l; a++)
var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () =>( for (var a = 0; a< arr.length; ++a)
var b = arr[a] + 1;
}]
, ["reverse for-loop", () =>( for(var a = arr.length - 1; a >= 0; --a) var b = arr[a] + 1; )] ,["while-loop", () => ( var a = 0 , l = arr.length;< l) {
var b = arr[a] + 1;
++a;
}
}]
, ["reverse-do-while-loop", () =>( var a = arr.length - 1; // CAREFUL do ( var b = arr[a] + 1; ) while(a--); )] , ["forEach", () => ( arr.forEach( a => ( var b = a + 1; )); ; for(const a in ar) ( var b = a + 1; ) )] , ["Duff device", () => ( var i = 0; var r = arr.length % 8; var n = (arr .length - r) / 8; if (r > 0) do (var b = arr + 1; ) while (--r); if (n > 0) do (var b = arr [i] + 1; c = arr + 1; var d = arr + 1; --n >>> 3; ) while (n); ], ["Duff device negative", () => ( var r = arr.length % 8; var n = (arr.length-r) / 8 ; ///Math.floor(arr.length / 8); (n) (var b = arr [i] + 1; var c = arr + 1; var d = arr + 1; var e = arr + 1; var f = arr + 1; var g = arr + 1; var h = arr + 1; var j = arr + 1; function bench(title, f) ( var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log("$(title) took $(t1-t0) ) msec"); ) var globalVarTime = bench("for-loop without "var"", () => ( // Тут ви знайдете "Var" з параметрами"ll be global for(a = 0, l = arr.length;< l; ++a)
var b = arr[a] + 1;
});
var times = benches.map(function(a) {
arr = new Array(11111111).fill(255);
return
}).sort((a,b) =>a-b); var max = times; times = times.map(a => (a = (a/max)*100; return a; )); var template = (title, time, n) => "
2014 While тому Подумайте логічно. Подивіться на це For(var index = 0 , length = array.length ; index< length ; index++) {
//do stuff
}
Тепер скажіть мені, чому це має бути швидше, ніж: Var length = array.length; while(--length) ( //or length-- //do stuff ) Я був повністю спантеличений, коли Chrome 28 показав, що цикл for працює швидше, ніж час. Це має бути якось "Ну кожен використовує цикл for, нехай фокусується на цьому, коли для хром ". Але тепер, у 2014 році, цикл while повертається на хром. він у 2 рази швидше, в інших/старих браузерах він завжди був швидшим. Останнім часом я зробив кілька тестів. Тепер у реальному світі envoirement ці короткі коди нічого не варті, і jsperf не може фактично правильно виконати цикл while, тому що йому потрібно відтворити array.length, що також вимагає часу. НЕ МОЖЕ отримати фактичну швидкість циклу, коли на jsperf. вам потрібно створити свою власну функцію та перевірити, що за допомогою window.performance.now() І так... немає ніякого способу, щоб цикл while був швидше. Реальна проблема - це фактичне маніпулювання/час відтворення/час малювання або ви хочете називати його. Наприклад, у мене є сцена canvas, де мені потрібно обчислити координати та колізії... це робиться між 10-200 MicroSeconds (не мілісекундами). він фактично приймає різні мілісекунди, щоб зробити все. Так само, як у DOM. У деяких випадках існує ще один суперефективний спосіб використання loop ... наприклад, для копіювання/клонування масиву For(var i = array.length ; i > 0 ; arrayCopy [--i] = array [i] // doing stuff); Зверніть увагу на налаштування параметрів: Сказано, що це підтверджує, що машини, такі як писав, що я думав, щоб зробити його трохи коротше і видалити деякі непотрібні речі і написав цей, використовуючи той же стиль: For(var i = array.length ; i-- ; arrayCopy [i] = array [i] // doing stuff); Навіть якщо це коротше, схоже, що використання ще раз уповільнює все. Це на 1/5 повільніше за попередній цикл for і While. Примітка:; дуже важливо після того, як для looo без () Навіть якщо я тільки-но сказав вам, що jsperf - це не найкращий спосіб протестувати скрипти. Я додав тут 2 цикли. І ось ще одна відповідь про продуктивність у javascript Ця відповідь має показати виконавчі способи написання JavaScript. Тому, якщо ви не можете прочитати це, запитайте і ви отримаєте відповідь або прочитаєте книгу про javascript http://www.ecma-international.org/ecma-262/5.1/
Остання ревізія тесту, яку я підготував (шляхом повторного використання старішого), показує одну річ. Довжина кешування не така важлива, але це не шкодить. Кожен перший запуск тесту, пов'язаного вище (на вкладці, що недавно відкрилася), дає найкращі результати для останніх 4 фрагментів (3-й, 5-й, 7-й і 10-й в діаграмах) в Chrome, Opera і Firefox на моєму 64- бітному Debian Squeeze (моє настільне обладнання). Наступні прогони дають зовсім інший результат. Висновки щодо продуктивності прості: В даний час (2011.10) нижче шаблон виглядає як найшвидший. For (var i = 0, len = arr.length; i !== len; i++) ( ... ) Пам'ятайте, що кешування arr.length тут не має вирішального значення, тому ви можете просто протестувати i !== arr.length , і продуктивність не знизиться, але ви отримаєте коротший код. PS: Я знаю, що у фрагменті з shift() його результат можна використовувати замість доступу до 0-го елементу, але я чомусь забував, що після повторного використання попередньої ревізії (яка мала неправильне значення під час циклів), а пізніше я не хотів втрачати вже отримані результати.
"Найкращий", як у чистому виконанні? або продуктивність І? Чиста продуктивність "найкраща" - це те, що використовує кеш та префіксний оператор ++ (мої дані: http://jsperf.com/caching-array-length/189) For (var i = 0, len = myArray.length; i< len; ++i) {
// blah blah
}
Я б сказав, що цикл без кешу - найкращий баланс часу виконання та часу читання програміста. Кожен програміст, що починається з C/C++/Java, не витрачатиме мс, щоб прочитати цей For(var i=0; i< arr.length; i++){
// blah blah
}
** Кешуйте довжину масиву всередині циклу, деякі секунди часу будуть вислизати. Залежить від елементів у масиві, якщо в масиві є більше елементів, існує велика різниця щодо Ms часу * SArr; // Array; for(var i = 0; i SArr; // Array; for(var i = 0,len = sArr.length ; i< len ; i++) {
callArray(sArr[i]); //function call
}
***end: 1.354ms***
Це рік 2017
. Я зробив кілька тестів. Схоже, метод while є найшвидшим у Chrome. Схоже, що лівий декремент (--i) набагато швидше за інших (++i, i--, i++) в Firefox. Цей підхід є постом у середньому. Але він виконує ітерацію масиву у зворотному порядку. Let i = array.length; while (--i >= 0) ( doSomething(array[i]); ) Якщо пріоритетний порядок є важливим, використовуйте цей підхід. Let ii = array.length; let i = 0; while (i< ii) {
doSomething(array[i]);
++i;
}
Я завжди пишу у першому стилі. Навіть якщо компілятор досить розумний, щоб оптимізувати його для масивів, але все ж таки він розумний, якщо ми використовуємо DOMNodeList тут або якийсь складний об'єкт з розрахованою довжиною? Я знаю, що питання про масиви, але я вважаю гарною практикою писати всі ваші петлі в одному стилі.
Var arr =; // The array var i = 0; while (i< arr.length) {
// Do something with arr[i]
i++;
}
i ++ швидше, ніж ++ i, --i і я -Метод forEach
Метод filter
Метод map
Методи every/some
reduce/reduceRight
sum
current
result
перший виклик
1
1
другий виклик
1
2
3
третій виклик
3
3
6
четвертий виклик
6
4
10
п'ятий виклик
10
5
15
Підсумки
Завдання
Отримайте новий масив
Відфільтруйте масив
Перевірити масив
I. Перебір реальних масивів
На даний момент є три способи перебору елементів цього масиву:
Крім того, незабаром, з появою нового стандарту ECMAScript 6 (ES 6), очікується ще два способи: 1. Метод forEach і споріднені методи
Якщо ваш проект розрахований на підтримку можливостей стандарту ECMAScript 5 (ES5), можна використовувати одне з його нововведень - метод forEach .
var a = ["a", "b", "c"]; a.forEach(function(entry) ( console.log(entry); ));
У загальному випадку використання forEach потребує підключення бібліотеки емуляції es5-shim для браузерів, які не мають нативної підтримки цього методу. До них відносяться IE 8 і раніше версії, які до цих пір де-не-де ще використовуються.2. Цикл for
Старий добрий for рулит:
Якщо довжина масиву незмінна протягом усього циклу, а сам цикл належить критичній у плані продуктивності ділянці коду (що малоймовірно), то можна використовувати більш оптимальну версію for зі зберіганням довжини масиву:
Теоретично цей код має виконуватися трохи швидше, ніж попередній.
Тим не менш, у сучасних движках JavaScript подібні ігри з оптимізацією зазвичай нічого не означають.3. Правильне використання циклу for...in
Якщо вам порадять використовувати цикл for ... in, пам'ятайте, що перебір масивів - не те, для чого він призначений. Попри поширену оману цикл for...in перебирає не індекси масиву, а перераховані властивості об'єкта.
У цьому прикладі кожної ітерації циклу виконується дві перевірки:
Звичайно, такі перевірки заберуть зайвий час під час виконання циклу. Але у разі розрідженого масиву цей спосіб ефективніший, ніж цикл for, оскільки в цьому випадку перебираються ті елементи, які явно визначені в масиві. Так, у прикладі вище буде виконано всього 3 ітерації (для індексів 0, 10 та 10000) - проти 10001 у циклі for .
Тоді тіло циклу із прикладу значно скоротиться:
Розглянутий вище код перевірок є універсальним, придатним всім випадків. Але замість нього можна використовувати більш коротку версію, хоча формально і не зовсім правильну, проте, придатну для більшості випадків:4. Цикл for...of (неявне використання ітератора)
ES6, поки все ще перебуває в статусі чернетки, повинен ввести JavaScript ітератори.
Ітератор - це об'єкт, у якому визначено метод next() - функція без аргументів, що повертає об'єкт із двома властивостями:
Багато вбудованих об'єктів, у т.ч. справжні масиви мають ітератори за замовчуванням. Найпростіший спосіб застосування ітератора у справжніх масивах - використовувати нову конструкцію for...of.
У наведеному прикладі цикл for...of неявно викликає ітератор об'єкта Array щоб одержати кожного значення масиву.5. Явне використання ітератора
Ітератори можна також використовувати і явно, щоправда, у цьому випадку код стає значно складнішим, порівняно з циклом for...of. Виглядає це приблизно так:
У цьому прикладі метод Array.prototype.entries повертає ітератор, який використовується для виведення значень масиву. На кожній ітерації entry.value міститься масив виду [ключ, значення] .ІІ. Перебір масивоподібних об'єктів
Крім справжніх масивів, JavaScript зустрічаються також масивоподібні об'єкти
. Зі справжніми масивами їх ріднить те, що вони мають властивість length і властивості з іменами у вигляді чисел, що відповідають елементам масиву. Як приклади можна назвати DOM колекції NodeList і псевдомасив arguments, доступний всередині будь-якої функції/методу. 1. Використання способів перебору реальних масивів
Як мінімум більшість, якщо не всі способи перебору справжніх масивів можуть бути застосовані для перебору масивоподібних об'єктів.
Для зручності повторного використання цього прийому, можна оголосити посилання на метод Array.prototype.forEach в окремій змінній та використовувати його як скорочення:
Якщо масивоподобном об'єкті є ітератор, його можна використовувати явно чи неявно для перебору об'єкта так само, як і справжніх масивів.2. Перетворення на справжній масив
Є також ще один, дуже простий спосіб перебору масивоподібного об'єкта: перетворити його в справжній масив і використовувати будь-який з розглянутих вище способів перебору справжніх масивів. Для перетворення можна використовувати універсальний метод Array.prototype.slice, який може бути застосований до будь-якого масивного об'єкта. Робиться це дуже просто, як показано на прикладі нижче:
Наприклад, якщо ви хочете перетворити колекцію NodeList на справжній масив, вам потрібен приблизно такий код:
Update: Як було зазначено у коментаряхforEach
filter
every/some
map
reduce/reduceRight
for-loop без "var" $(globalVarTime) msec."; var $container = document.getElementById("container"); $container.innerHTML = strRes; body ( color:#fff; background:#333; font-family :helvetica; ) body > div > div ( clear:both ) body > div > div > span ( float:left; width:43%; margin:3px 0; text-align:right; ) body > div > div > span :nth-child(2) ( text-align:left; background:darkorange; animation:showup .37s .111s; -webkit-animation:showup .37s .111s; ) @keyframes showup ( from ( width:0; ) ) @-webkit-keyframes showup ( from ( width:0; ) )