массивы и циклы / Хабр
Сегодня, в пятой части перевода курса по JavaScript, мы поговорим о массивах и циклах. Массивы используются в ходе решения множества задач. Часто с массивами работают, используя циклы.
→ Часть 1: первая программа, особенности языка, стандарты
→ Часть 2: стиль кода и структура программ
→ Часть 3: переменные, типы данных, выражения, объекты
→ Часть 4: функции
→ Часть 5: массивы и циклы
→ Часть 6: исключения, точка с запятой, шаблонные литералы
→ Часть 7: строгий режим, ключевое слово this, события, модули, математические вычисления
→ Часть 8: обзор возможностей стандарта ES6
→ Часть 9: обзор возможностей стандартов ES7, ES8 и ES9
Массивы
Массивы, объекты типа Array
, развиваются вместе с остальными механизмами языка. Они представляют собой списки пронумерованных значений.
Первый элемент массива имеет индекс (ключ) 0, такой подход используется во многих языках программирования.
В этом разделе мы рассмотрим современные методы работы с массивами.
▍Инициализация массивов
Вот несколько способов инициализации массивов.
const a = [] const a = [1, 2, 3] const a = Array.of(1, 2, 3) const a = Array(6).fill(1) //инициализация каждого элемента массива, состоящего из 6 элементов, числом 1
Для того чтобы получить доступ к отдельному элементу массива, используют конструкцию, состоящую из квадратных скобок, в которых содержится индекс элемента массива. Элементы массивов можно как считывать, так и записывать.
const a = [1, 2, 3] console.log(a) //[ 1, 2, 3 ] const first = a[0] console.log(first) //1 a[0] = 4 console.log(a) //[ 4, 2, 3 ]
Конструктор Array
для объявления массивов использовать не рекомендуется.
const a = new Array() //не рекомендуется const a = new Array(1, 2, 3) //не рекомендуется
Этот способ следует использовать лишь при объявлении типизированных массивов.
▍Получение длины массива
Для того чтобы узнать длину массива, нужно обратиться к его свойству length
.
const l = a.length
▍Проверка массива с использованием метода every()
Метод массивов every()
можно использовать для организации проверки всех их элементов с использованием некоего условия. Если все элементы массива соответствуют условию, функция возвратит true
, в противном случае она возвратит false
.
Этому методу передаётся функция, принимающая аргументы currentValue
(текущий элемент массива), index
(индекс текущего элемента массива) и
(сам массив). Он может принимать и необязательное значение, используемое в качестве this
при выполнении переданной ему функции.
Например, проверим, превышают ли значения всех элементов массива число 10.
const a = [11, 12, 13] const b = [5, 6, 25] const test = el => el > 10 console.log(a.every(test)) //true console.log(b.every(test)) //false
Здесь нас, в функции test()
, интересует лишь первый передаваемый ей аргумент, поэтому мы объявляем её, указывая лишь параметр el
, в который и попадёт соответствующее значение.
▍Проверка массива с использованием метода some()
Этот метод очень похож на метод every()
, но он возвращает true
, если хотя бы один из элементов массива удовлетворяет условию, заданному переданной ему функцией.
▍Создание массива на основе существующего массива с использованием метода map()
Метод массивов map()
позволяет перебирать массивы, применяя к каждому их элементу, переданную этому методу, функцию, преобразующую элемент, и создавать из полученных значений новые массивы. Вот, например, как получить новый массив, являющийся результатом умножения всех элементов исходного массива на 2.
const a = [1, 2, 3] const double = el => el * 2 const doubleA = a.map(double) console.log(a) //[ 1, 2, 3 ] console.log(doubleA) //[ 2, 4, 6 ]
▍Фильтрация массива с помощью метода filter()
Метод filter()
похож на метод map()
, но он позволяет создавать новые массивы, содержащие лишь те элементы исходных массивов, которые удовлетворяют условию, задаваемому передаваемой методу filter()
функцией.
▍Метод reduce()
reduce()
позволяет применить заданную функцию к аккумулятору и к каждому значению массива, сведя массив к единственному значению (это значение может иметь как примитивный, так и объектный тип). Этот метод принимает функцию, выполняющую преобразования, и необязательное начальное значение аккумулятора.
const a = [1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { return accumulator * currentValue }, 1) console.log(a) //24 //итерация 1: 1 * 1 = 1 //итерация 2: 1 * 2 = 2 //итерация 3: 2 * 3 = 6 //итерация 4: 6 * 4 = 24
Здесь мы ищем произведение всех элементов массива, описанного с помощью литерала, задавая в качестве начального значения аккумулятора 1.
▍Перебор массива с помощью метода forEach()
Метод массивов forEach()
можно использовать для перебора значений массивов и для выполнения над ними неких действий, задаваемых передаваемой методу функцией. Например, выведем, по одному, элементы массива в консоль.
const a = [1, 2, 3] a.forEach(el => console.log(el)) //1 //2 //3
Если при переборе массива нужно остановить или прервать цикл, то при использовании forEach()
придётся выбрасывать исключение. Поэтому если в ходе решения некоей задачи может понадобиться прерывание цикла, лучше всего выбрать какой-нибудь другой способ перебора элементов массива.
▍Перебор массива с использованием оператора for…of
Оператор for...of
появился в стандарте ES6. Он позволяет перебирать итерируемые объекты (в том числе — массивы). Вот как им пользоваться.
const a = [1, 2, 3] for (let v of a) { console.log(v) } //1 //2 //3
На каждой итерации цикла в переменную v
попадает очередной элемент массива a
.
▍Перебор массива с использованием оператора for
Оператор for
позволяет организовывать циклы, которые, в частности, можно использовать и для перебора (или инициализации) массивов, обращаясь к их элементам по индексам. Обычно индекс очередного элемента получают, пользуясь счётчиком цикла.
const a = [1, 2, 3] for (let i = 0; i < a.length; i += 1) { console.log(a[i]) } //1 //2 //3
Если, в ходе выполнения цикла, нужно пропустить его итерацию, можно воспользоваться командой continue
. Для досрочного завершения цикла можно воспользоваться командой break
. Если в цикле, например, расположенном в некоей функции, использовать команду return
, выполнение цикла и функции завершится, а возвращённое с помощью return
значение попадёт туда, откуда была вызвана функция.
▍Метод @@iterator
Этот метод появился в стандарте ES6. Он позволяет получать так называемый «итератор объекта» — объект, который в данном случае позволяет организовывать перебор элементов массива. Итератор массива можно получить, воспользовавшись символом (такие символы называют «известными символами») Symbol.iterator
. После получения итератора можно обращаться к его методу next()
, который, при каждом его вызове, возвращает структуру данных, содержащую очередной элемент массива.
const a = [1, 2, 3] let it = a[Symbol.iterator]() console.log(it.next().value) //1 console.log(it.next().value) //2 console.log(it.next().value) //3
next()
после того, как будет достигнут последний элемент массива, он возвратит, в качестве значения элемента, undefined
. Объект, возвращаемый методом next()
, содержит свойства value
и done
. Свойство done
принимает значение false
до тех пор, пока не будет достигнут последний элемент массива. В нашем случае, если вызвать it.next()
в четвёртый раз, он возвратит объект { value: undefined, done: true }
, в то время как при трёх предыдущих вызовах этот объект имел вид { value: значение, done: false }
.Метод массивов entries()
возвращает итератор, который позволяет перебирать пары ключ-значение массива.
const a = [1, 2, 3] let it = a.entries() console.log(it.next().value) //[0, 1] console.log(it.next().value) //[1, 2] console.log(it.next().value) //[2, 3]
Метод keys()
позволяет перебирать ключи массива.
const a = [1, 2, 3] let it = a.keys() console.log(it.next().value) //0 console.log(it.next().value) //1 console.log(it.next().value) //2
▍Добавление элементов в конец массива
Для добавления элементов в конец массива используют метод push()
.
a.push(4)
▍Добавление элементов в начало массива
Для добавления элементов в начало массива используют метод unshift()
.
a.unshift(0) a.unshift(-2, -1)
▍Удаление элементов массива
Удалить элемент из конца массива, одновременно возвратив этот элемент, можно с помощью метода pop()
.
a.pop()
Аналогичным образом, с помощью метода shift()
, можно удалить элемент из начала массива.
a.shift()
То же самое, но уже с указанием позиции удаления элементов и их количества, делается с помощью метода splice()
.
a.splice(0, 2) // удаляет и возвращает 2 элемента из начала массива a.splice(3, 2) // удаляет и возвращает 2 элемента, начиная с индекса 3
▍Удаление элементов массива и вставка вместо них других элементов
Для того чтобы, воспользовавшись одной операцией, удалить некие элементы массива и вставить вместо них другие элементы, используется уже знакомый вам метод splice()
.
Например, здесь мы удаляем 3 элемента массива начиная с индекса 2, после чего в то же место добавляем два других элемента:
const a = [1, 2, 3, 4, 5, 6] a.splice(2, 3, 'a', 'b') console.log(a) //[ 1, 2, 'a', 'b', 6 ]
▍Объединение нескольких массивов
Для объединения нескольких массивов можно воспользоваться методом concat()
, возвращающим новый массив.
const a = [1, 2] const b = [3, 4] const c = a.concat(b) console.log(c) //[ 1, 2, 3, 4 ]
▍Поиск элементов в массиве
В стандарте ES5 появился метод indexOf()
, который возвращает индекс первого вхождения искомого элемента массива. Если элемент в массиве найти не удаётся — возвращается -1
.
const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.indexOf(5)) //4 console.log(a.indexOf(23)) //-1
Метод lastIndexOf()
возвращает индекс последнего вхождения элемента в массив, или, если элемент не найден, -1
.
const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.lastIndexOf(5)) //7 console.log(a.lastIndexOf(23)) //-1
В ES6 появился метод массивов find()
, который выполняет поиск по массиву с использованием передаваемой ему функции. Если функция возвращает true
, метод возвращает значение первого найденного элемента. Если элемент найти не удаётся, функция возвратит
undefined
.
Выглядеть его использование может следующим образом.
a.find(x => x.id === my_id)
Здесь в массиве, содержащем объекты, осуществляется поиск элемента, свойство id
которого равняется заданному.
Метод findIndex()
похож на find()
, но он возвращает индекс найденного элемента или undefined
.
В ES7 появился метод includes()
, который позволяет проверить наличие некоего элемента в массиве. Он возвращает true
или false
, найдя или не найдя интересующий программиста элемент.
a.includes(value)
С помощью этого метода можно проверять на наличие некоего элемента не весь массив, а лишь некоторую его часть, начинающуюся с заданного при вызове этого метода индекса. Индекс задаётся с помощью второго, необязательного, параметра этого метода.
a.includes(value, i)
▍Получение фрагмента массива
Для того чтобы получить копию некоего фрагмента массива в виде нового массива, можно воспользоваться методом slice()
. Если этот метод вызывается без аргументов, то возвращённый массив окажется полной копией исходного. Он принимает два необязательных параметра. Первый задаёт начальный индекс фрагмента, второй — конечный. Если конечный индекс не задан, то массив копируется от заданного начального индекса до конца.
const a = [1, 2, 3, 4, 5, 6, 7, 8, 9] console.log(a.slice(4)) //[ 5, 6, 7, 8, 9 ] console.log(a.slice(3,7)) //[ 4, 5, 6, 7 ]
▍Сортировка массива
Для организации сортировки элементов массива в алфавитном порядке (0-9A-Za-z
) используется метод sort()
без передачи ему аргументов.
const a = [1, 2, 3, 10, 11] a.sort() console.log(a) //[ 1, 10, 11, 2, 3 ] const b = [1, 'a', 'Z', 3, 2, 11] b.sort() console.log(b) //[ 1, 11, 2, 3, 'Z', 'a' ]
Этому методу можно передать функцию, задающую порядок сортировки. Функция принимает, для сравнения двух элементов, параметры a
и b
. Она возвращает отрицательное число в том случае, если a
меньше b
по какому-либо критерию, 0 — если они равны, и положительное число — если a
больше b
. При написании подобной функции для сортировки числовых массивов она может возвратить результат вычитания a
и b
. Так, возврат результата вычисления выражения a - b
означает сортировку массива по возрастанию, возврат результата вычисления выражения b - a
даст сортировку массива по убыванию.
const a = [1, 10, 3, 2, 11] console.log(a.sort((a, b) => a - b)) //[ 1, 2, 3, 10, 11 ] console.log(a.sort((a, b) => b - a)) //[ 11, 10, 3, 2, 1 ]
Для того чтобы обратить порядок следования элементов массива можно воспользоваться методом reverse()
. Он, так же, как и
sort()
, модифицирует массив для которого вызывается.
▍Получение строкового представления массива
Для получения строкового представления массива можно воспользоваться его методом toString()
.
a.toString()
Похожий результат даёт метод join()
, вызванный без аргументов.
a.join()
Ему, в качестве аргумента, можно передать разделитель элементов.
const a = [1, 10, 3, 2, 11] console.log(a.toString()) //1,10,3,2,11 console.log(a.join()) //1,10,3,2,11 console.log(a.join(', ')) //1, 10, 3, 2, 11
▍Создание копий массивов
Для создания копии массива путём копирования в новый массив значений исходного массива можно воспользоваться методом Array.from()
. Он подходит и для создания массивов из массивоподобных объектов (из строк, например).
const a = 'a string' const b = Array.from(a) console.log(b) //[ 'a', ' ', 's', 't', 'r', 'i', 'n', 'g' ]
Метод Array.of()
тоже можно использовать для копирования массивов, а также для «сборки» массивов из различных элементов. Например, для копирования элементов одного массива в другой можно воспользоваться следующей конструкцией.
const a = [1, 10, 3, 2, 11] const b = Array.of(...a) console.log(b) // [ 1, 10, 3, 2, 11 ]
Для копирования элементов массива в некое место самого этого массива используется метод copyWithin()
. Его первый аргумент задаёт начальный индекс целевой позиции, второй — начальный индекс позиции источника элементов, а третий параметр, необязательный, указывает конечный индекс позиции источника элементов. Если его не указать, в указанное место массива будет скопировано всё, начиная от начального индекса позиции источника до конца массива.
const a = [1, 2, 3, 4, 5] a.copyWithin(0, 2) console.log(a) //[ 3, 4, 5, 4, 5 ]
Циклы
Выше, говоря о массивах, мы уже сталкивались с некоторыми способами организации циклов. Однако циклы в JavaScript используются не только для работы с массивами, да и рассмотрели мы далеко не все их виды. Поэтому сейчас мы уделим некоторое время рассмотрению разных способов организации циклов в JavaScript и поговорим об их особенностях.
▍Цикл for
Рассмотрим пример применения этого цикла.
const list = ['a', 'b', 'c'] for (let i = 0; i < list.length; i++) { console.log(list[i]) //значения, хранящиеся в элементах циклов console.log(i) //индексы }
Как уже было сказано, прерывать выполнение такого цикла можно, используя команду break
, а пропускать текущую итерацию и переходить сразу к следующей можно с помощью команды continue
.
▍Цикл forEach
Этот цикл мы тоже обсуждали. Приведём пример перебора массива с его помощью.
const list = ['a', 'b', 'c'] list.forEach((item, index) => { console.log(item) //значение console.log(index) //индекс }) //если индексы элементов нас не интересуют, можно обойтись и без них list.forEach(item => console.log(item))
Напомним, что для прерывания такого цикла надо выбрасывать исключение, то есть, если при использовании цикла может понадобиться прервать его, лучше выбрать какой-нибудь другой цикл.
▍Цикл do…while
Это — так называемый «цикл с постусловием». Такой цикл будет выполнен как минимум один раз до проверки условия завершения цикла.
const list = ['a', 'b', 'c'] let i = 0 do { console.log(list[i]) //значение console.log(i) //индекс i = i + 1 } while (i < list.length)
Его можно прерывать с использованием команды break
, можно переходить на его следующую итерацию командой continue
.
▍Цикл while
Это — так называемый «цикл с предусловием». Если, на входе в цикл, условие продолжения цикла ложно, он не будет выполнен ни одного раза.
const list = ['a', 'b', 'c'] let i = 0 while (i < list.length) { console.log(list[i]) //значение console.log(i) //индекс i = i + 1 }
▍Цикл for…in
Этот цикл позволяет перебирать все перечислимые свойства объекта по их именам.
let object = {a: 1, b: 2, c: 'three'} for (let property in object) { console.log(property) //имя свойства console.log(object[property]) //значение свойства }
▍Цикл for…of
Цикл for...of
совмещает в себе удобство цикла forEach
и возможность прерывать его работу штатными средствами.
//перебор значений for (const value of ['a', 'b', 'c']) { console.log(value) //значение } //перебор значений и получение индексов с помощью `entries()` for (const [index, value] of ['a', 'b', 'c'].entries()) { console.log(index) //индекс console.log(value) //значение }
Обратите внимание на то, что здесь, в заголовке цикла, используется ключевое слово const
, а не, как можно было бы ожидать, let
. Если внутри блока цикла переменные не нужно переназначать, то const
нам вполне подходит.
Если сравнить циклы for...in
и for...of
, то окажется, что for...in
перебирает имена свойств, а for...of
— значения свойств.
Циклы и области видимости
С циклами и с областями видимости переменных связана одна особенность JavaScript, которая может доставить разработчику некоторые проблемы. Для того чтобы с этими проблемами разобраться, поговорим о циклах, об областях видимости, и о ключевых словах var
и let
.
Рассмотрим пример.
const operations = [] for (var i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
В цикле производится 5 итераций, на каждой из которых в массив operations
добавляется новая функция. Эта функция выводит в консоль значение счётчика цикла — i
. После того, как функции добавлены в массив, мы этот массив перебираем и вызываем функции, являющиеся его элементами.
Выполняя подобный код можно ожидать результата, показанного ниже.
0 1 2 3 4
Но на самом деле он выводит следующее.
5 5 5 5 5
Почему это так? Всё дело в том, что в качестве счётчика цикла мы используем переменную, объявленную с использованием ключевого слова var
.
Так как объявления подобных переменных поднимаются в верхнюю часть области видимости, вышеприведённый код аналогичен следующему.
var i; const operations = [] for (i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
В результате оказывается, что в цикле for...of
, в котором мы перебираем массив, переменная i
всё ещё видна, она равна 5, в результате, ссылаясь на i
во всех функциях, мы выводим число 5.
Как изменить поведение программы таким образом, чтобы она делала бы то, что от неё ожидается?
Самое простое решение этой проблемы заключается в использовании ключевого слова let
. Оно, как мы уже говорили, появилось в ES6, его использование позволяет избавиться от некоторых странностей, характерных для var
.
В частности, в вышеприведённом примере достаточно изменить var
на let
и всё заработает так, как нужно.
const operations = [] for (let i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
Теперь на каждой итерации цикла каждая функция, добавленная в массив operations
, получает собственную копию i
. Помните о том, что в данной ситуации нельзя использовать ключевое слово
const
, так как значение i
в цикле меняется.
Ещё один способ решения этой проблемы, который часто применялся до появления стандарта ES6, когда ключевого слова let
ещё не было, заключается в использовании IIFE.
При таком подходе значение i
сохраняется в замыкании, а в массив попадает функция, возвращаемая IIFE и имеющая доступ к замыканию. Эту функцию можно выполнить тогда, когда в ней возникнет необходимость. Вот как это выглядит.
const operations = [] for (var i = 0; i < 5; i++) { operations.push(((j) => { return () => console.log(j) })(i)) } for (const operation of operations) { operation() }
Итоги
Сегодня мы поговорили о массивах и о циклах в JavaScript. Тема нашего следующего материала — обработка исключений, особенности использования точки с запятой и шаблонные литералы.
Уважаемые читатели! Какими методами для работы с массивами в JavaScript вы пользуетесь чаще всего?
Анализ производительности и эффективности цикла JS-массива (for, while, forEach, map, for of)
Постоянная ссылка на эту статью:github.com/HaoChuan942…
Предисловие
Внешняя разработка часто включает операции, связанные с массивами: дедупликацию, фильтрацию, суммирование, вторичную обработку данных и так далее. Оба требуют, чтобы мы перебрали массив. Чтобы удовлетворить различные потребности, JS предоставляет простейшиеfor
ЗациклитьсяES6
И новые в последующих версиях, такие как:map、filter、some、reduce
И другие практические приемы. Поскольку каждый метод имеет разные функции, несправедливо и бессмысленно просто сравнивать скорость выполнения всех методов, включающих циклы. Затем мы нацеленыСамая простая петля для этой целиВыполните тест производительности и эффективности видимым невооруженным глазом, чтобы обсудить эти распространенные методы цикла массивов в JS.
Говоря с самого простого цикла for
for
Четыре распространенных способа написания циклов, не длинных, прямо в кодеconst persons = ['Чжэн Хаочуань', 'Чжун Чжун', "Гао Сяобо", 'Wei Guitie', Ян Цзюнь, "Песня может"]
// метод первый
for (let i = 0; i < persons.length; i++) {
console.log(persons[i])
}
// Метод второй
for (let i = 0, len = persons.length; i < len; i++) {
console.log(persons[i])
}
// Метод третий
for (let i = 0, person; person = persons[i]; i++) {
console.log(person)
}
// Метод четвертый
for (let i = persons.length; i--;) {
console.log(persons[i])
}
Скопировать код
Первый способ — самый распространенный, без объяснения причин.
Второй способ —
persons.length
Кэшировать в переменнуюlen
Таким образом, длина массива не будет считываться при каждом цикле.Третий метод состоит в том, чтобы объединить значение и суждение и непрерывно перебирать каждый элемент перечисления, пока перечисление не достигнет нулевого значения, цикл завершится.
Порядок исполнения:
Четвертый метод — это обратный цикл. Порядок исполнения:
Четыре вида
for
Тест производительности и скорости цикла в мелкой копии массиваСначала создайте массив, длина которого соответствует копируемой цели (еслиi
Если значение слишком велико, около 100 миллионов, может возникнуть ошибка трассировки стека JS)
const ARR_SIZE = 6666666
const hugeArr = new Array(ARR_SIZE).fill(1)
Скопировать код
Затем используйте четыре метода цикла, чтобы извлечь каждый элемент в массиве и добавить его в пустой массив, который является мелкой копией массива. И пройтиconsole.timeс участиемconsole.timeEndЗапишите общее время выполнения каждого режима цикла. отprocess.memoryUsage()Сравните разницу между используемой кучей памяти до и после выполнения.
/ * Разница между используемой кучей в памяти до и после выполнения метода в среде узла * /
function heapRecord(fun) {
if (process) {
const startHeap = process.
memoryUsage().heapUsed
fun()
const endHeap = process.memoryUsage().heapUsed
const heapDiff = endHeap - startHeap
console.log('Отличие используемой кучи:', heapDiff)
} else {
fun()
}
}
Скопировать код
// Метод первый, обычный для цикла
function method1() {
var arrCopy = []
console.time('method1')
for (let i = 0; i < hugeArr.length; i++) {
arrCopy.push(hugeArr[i])
}
console.timeEnd('method1')
}
// Метод второй, длина буфера
function method2() {
var arrCopy = []
console.time('method2')
for (let i = 0, len = hugeArr.length; i < len; i++) {
arrCopy.push(hugeArr[i])
}
console.timeEnd('method2')
}
// Метод третий, сочетающий ценность и суждение
function method3() {
var arrCopy = []
console.time('method3')
for (let i = 0, item; item = hugeArr[i]; i++) {
arrCopy.push(item)
}
console.timeEnd('method3')
}
// Метод четвертый, i - объединить с оценкой, итерация в обратном порядке
function method4() {
var arrCopy = []
console.
time('method4')
for (let i = hugeArr.length; i--;) {
arrCopy.push(hugeArr[i])
}
console.timeEnd('method4')
}
Скопировать код
Вызовите указанные выше методы отдельно, повторите каждый метод 12 раз, удалите максимальное и минимальное значение и найдите среднее значение (округление вверх). Окончательные результаты времени выполнения каждого метода следующие (тестовая машина:MacBook Pro (15 дюймов, 2017 г.) Процессор: 2,8 ГГц Intel Core i7 Оперативная память: 16 ГБ 2133 МГц LPDDR3
Среда исполнения:node v10.8.0
):
— | метод первый | Метод второй | Метод третий | Метод четвертый |
---|---|---|---|---|
первый раз | 152.201ms | 156.990ms | 152.668ms | 152.684ms |
второй раз | 150.047ms | 159.166ms | 159.333ms | 152.455ms |
третий раз | 155.390ms | 151.823ms | 159.365ms | 149.809ms |
в четвертый раз | 153.![]() | 155.994ms | 155.325ms | 150.562ms |
пятый раз | 151.823ms | 154.689ms | 156.483ms | 148.067ms |
в шестой раз | 152.715ms | 154.677ms | 153.135ms | 150.787ms |
Седьмой раз | 152.084ms | 152.587ms | 157.458ms | 152.572ms |
В восьмой раз | 152.509ms | 153.781ms | 153.277ms | 152.263ms |
В девятый раз | 154.363ms | 156.497ms | 151.002ms | 154.310ms |
В десятый раз | 153.784ms | 155.612ms | 161.767ms | 153.487ms |
Среднее время | 152.811ms | 155.182ms | 155.981ms | 151.700ms |
Разница стека | 238511136Byte | 238511352Byte | 238512048Byte | 238511312Byte |
Это было неожиданно? Удивлен? Представьте, что хотя бы второй метод определенно быстрее первого! Но это не так. Я не верил фактам под рукой.Проверял много раз, в том числе менял длину скопированного массива с сотен до десятков миллионов. Наконец нашел: в
node
Для выполнения задач поверхностного копирования одного и того же массива в процессе выполнения разница во времени между четырьмя методами минимальна, а иногда сортировка даже немного колеблется. Использование памяти:Метод 1 <Метод 4 <Метод 2 <Метод 3, Но и разрыв очень мал.
двигатель v8
Новая версия нацеленаЦенность объектаОстальные операции оптимизированы для максимальной производительности, поэтому длина массива кеша во втором методе является переменной.len
Явного улучшения не будет. Даже миллионы данных, четыредля цикла
Длительный промежуток составляет всего миллисекунды, и четыре метода цикла for в занимаемой памяти также очень близки. Спасибо здесьYaHuiLiang、Мистер Семь секунд、Ге Сюньмоу doxP、Супер большой столбДля получения помощи и исправлений, если у вас есть лучшее понимание, прокомментируйте и оставьте сообщение.
то же самое сдвигатель v8
изГугл Хром
, Тест показал, что эти четыре метода также очень близки.
Но когдаБраузер Firefox
Результаты тестов в:Метод 2 ≈ Метод 3 ≈ Метод 4 <Метод 1, Указывая на то, что три стиля письма — два, три и четыре — можно в определенной степени оптимизировать.для цикла
Пока вбраузер сафари
:Метод 4 <Метод 1 ≈ Метод 2 ≈ Метод 3,толькоМетод четвертыйОтражает небольшой эффект оптимизации.
резюме
Принимая во внимание производительность и эффективность в разных средах или браузерах:
рекомендую
:Четвертыйi--
Метод обратного цикла. В этой статье Qi Dance Group——Привет, отправляем вам карту оптимизации веб-производительностииз2.3 Управление процессом
Этот метод также немного упоминается в разделе.
Не рекомендуется
:Третийпуть. В основном потому, что когда нетTruthy
Когда значение0
с участием''
, Приведет к непосредственному завершению цикла.
while
Петля иНовый синтаксис ES6 + для каждого
、map
с участиемfor of
, Быстрее будет?Не многословный, практика — единственный критерий проверки истины.
// Метод пятый, а
function method5() {
var arrCopy = []
console.time('method5')
let i = 0
while (i < hugeArr.length) {
arrCopy.push(hugeArr[i++])
}
console.timeEnd('method5')
}
// Метод шестой, forEach
function method6() {
var arrCopy = []
console.time('method6')
hugeArr.forEach((item) => {
arrCopy.push(item)
})
console.timeEnd('method6')
}
// Метод седьмой, карта
function method7() {
var arrCopy = []
console.time('method7')
arrCopy = hugeArr.map(item => item)
console.timeEnd('method7')
}
// Метод восьмой, для of
function method8() {
var arrCopy = []
console.time('method8')
for (let item of hugeArr) {
arrCopy.push(item)
}
console.timeEnd('method8')
}
Скопировать код
Метод проверки такой же, как и выше, результат проверки:
— | Метод пятый | Метод шестой | Метод седьмой | Метод восьмой |
---|---|---|---|---|
первый раз | 151.![]() | 221.332ms | 875.402ms | 240.411ms |
второй раз | 152.031ms | 223.436ms | 877.112ms | 237.208ms |
третий раз | 150.442ms | 221.853ms | 876.829ms | 253.744ms |
в четвертый раз | 151.319ms | 222.672ms | 875.270ms | 243.165ms |
пятый раз | 150.142ms | 222.953ms | 877.940ms | 237.825ms |
в шестой раз | 155.226ms | 225.441ms | 879.223ms | 240.648ms |
Седьмой раз | 151.254ms | 219.965ms | 883.324ms | 238.197ms |
В восьмой раз | 151.632ms | 218.274ms | 878.331ms | 240.940ms |
В девятый раз | 151.412ms | 223.189ms | 873.318ms | 256.644ms |
В десятый раз | 155.563ms | 220.595ms | 881.203ms | 234.![]() |
Среднее время | 152.040ms | 221.971ms | 877.795ms | 242.332ms |
Разница стека | 238511400Byte | 238511352Byte | 53887824Byte | 191345296Byte |
вnode
Далее, из приведенных выше данных хорошо видно,forEach
、map
с участиемfor of
Вот этиES6+
Грамматика нетрадиционнаfor
Петля илиwhile
Цикл быстрая, особенноmap
метод. Однако из-заmap
Есть возвращаемое значение, новый массив вызывать не нужноpush
Метод, поэтому использование памяти очень мало при выполнении задач неглубокого копирования. а такжеfor of
Синтаксис также имеет определенные преимущества в использовании памяти. Кстати:для цикла while цикл for of цикл
Может пройтиbreak
Выскакивает ключевое слово, иforEach map
Такого цикла невозможно избежать.
Однако, поскольку среда выполнения и браузер различаются, эти грамматики также будут иметь отклонения или даже инверсии в скорости выполнения. Просто посмотрите на картинку:
Гугл Хром
Браузер Firefox
браузер сафари
Как можно видеть:
- Гугл Хром
ES6+
Синтаксис цикла обычно медленнее, чем традиционный синтаксис цикла, но в Firefox и Safari ситуация почти противоположная. - Время выполнения различных синтаксисов циклов в Google Chrome не сильно отличается. но
map
В частности, скорость явно ниже, чем у некоторых других грамматик, но в Firefox и Safari происходит обратное.map
Это быстрее! - Яблочный Дафа — это хорошо
подводить итоги
Я слышал такие высказывания, как «длина буферного массива может повысить эффективность цикла» или «синтаксис цикла ES6 более эффективен». Говорящий непреднамерен, слушатель намерен, каковы факты, истинное знание приходит из практики. Независимо от бизнес-сценариев и простоты использования, просто говорить о производительности и эффективности бессмысленно. Множество новых методов массивов в ES6 значительно облегчают разработку интерфейса, делая сложный или длинный код в прошлом легким для чтения, кратким и хорошим.
for
Метод круговой записи имеет лучшую совместимость и производительность в различных средах в случае больших объемов данных. Конечно, обсуждение в этой статье — это только резюме, основанное на наблюдениях, и не углубляется в нижний слой. С обновлением браузеров плюсы и минусы этих методов могут стать метафизикой. В настоящее время находится вChrome Canary 70.0.3513.0
подfor of
Будет значительно лучше, чемChrome 68.0.3440.84
быстро. Если у вас есть более глубокие идеи или статьи, вы можете поделиться ими в области комментариев.Эта статья моего брата также является хорошей идеей. Если вас также интересуют производительность и эффективность других методов цикла для массивов, вы можете попробовать это самостоятельно и приветствовать комментарии и обмен мнениями.
Тестовая среда этой статьи:
node v10.8.0
、Chrome 68.0.3440.84
、Safari 11.1.2 (13605.3.8)
、Firefox 60.0
.forEach() — JavaScript — Дока
Кратко
Секция статьи «Кратко»Метод массива for
позволяет применить колбэк-функцию ко всем элементам массива. Можно использовать вместо классического цикла for
. В отличие от него for
выглядит более читабельным и понятным.
Пример
Секция статьи «Пример»const numbers = [1, 2, 3, 4]numbers.forEach((num) => { const square = num * num console.log('Квадрат числа равен: ' + square)})
const numbers = [1, 2, 3, 4]
numbers.forEach((num) => {
const square = num * num
console.log('Квадрат числа равен: ' + square)
})
Выведет:
Квадрат числа равен: 1 Квадрат числа равен: 4 Квадрат числа равен: 9 Квадрат числа равен: 16
Интерактивный пример:
Открыть демо в новой вкладкеСовсем любопытные могут заглянуть в исходники, чтобы посмотреть как for
активно используется в коде этого примера.
Как пишется
Секция статьи «Как пишется»Для того чтобы использовать for
, понадобится колбэк-функция, которую необходимо передавать в метод. Функцию можно объявить заранее:
function sliceFruit(fruit) { console.log('Разрезаю ' + fruit + '!')}const fruits = ['🍎', '🍊', '🍋', '🍓', '🥝']fruits.forEach(sliceFruit)
function sliceFruit(fruit) {
console.log('Разрезаю ' + fruit + '!')
}
const fruits = ['🍎', '🍊', '🍋', '🍓', '🥝']
fruits.forEach(sliceFruit)
Или создать её прямо в месте вызова:
const food = ['🍔', '🍟', '🍦']food.forEach((item) => { console.log('Мам, купи ' + item + '!')})
const food = ['🍔', '🍟', '🍦']
food.forEach((item) => {
console.log('Мам, купи ' + item + '!')
})
Важно знать, какие параметры принимает колбэк. Всего их три:
item
— элемент массива в текущей итерации;index
— индекс текущего элемента;arr
— сам массив, который мы перебираем.
Вернёмся к примеру с едой:
const food = ['🍔', '🍟', '🍦']food.forEach((item, index, arr) => { console.log('Текущий элемент ' + item) console.log('Его индекс ' + index) console.log('Исходный массив ' + arr)})
const food = ['🍔', '🍟', '🍦']
food.forEach((item, index, arr) => {
console.log('Текущий элемент ' + item)
console.log('Его индекс ' + index)
console.log('Исходный массив ' + arr)
})
Выведет:
Текущий элемент 🍔 Его индекс 0 Исходный массив ['🍔', '🍟', '🍦'] Текущий элемент 🍟 Его индекс 1 Исходный массив ['🍔', '🍟', '🍦'] Текущий элемент 🍦 Его индекс 2 Исходный массив ['🍔', '🍟', '🍦']
Как это понять
Секция статьи «Как это понять»Метод for
можно использовать, когда вам необходимо совершить одну и ту же операцию над всеми элементами массива.
Хотя в JavaScript уже есть возможность делать это, используя цикл for
, метод for
— это отличная альтернатива с рядом преимуществ:
- Использование метода
for
является декларативным способом обозначить нашу операцию.Each ( ) С точки зрения читабельности кода это больше приближено к естественному языку и лаконично.
- Позволяет удобно получать элемент в текущей итерации, без необходимости всякий раз обращаться к массиву по индексу.
Однако вместе с тем мы получаем и несколько недостатков:
- В
for
не будут работатьEach ( ) return
,break
иcontinue
, а следовательно, мы никак не можем прервать или пропустить итерацию. Потому, если для решения задачи необходимо воспользоваться каким-либо из этих операторов, придётся использовать обычный циклfor
. for
обрабатывает элементы массива в прямом порядке, то есть мы не можем пройти по массиву с конца.Each ( )
💡 Метод for
автоматически встроен в любой массив.
Сработает:
const empty = []const someNums = [1, 2, 3]console.log(empty.forEach)// Выведет функциюconsole.log(someNums.forEach)// И здесь тожеconst obj = {}console.log(obj.forEach)// undefined, потому что у объектов нет такого метода
const empty = [] const someNums = [1, 2, 3] console.log(empty.forEach) // Выведет функцию console.log(someNums.forEach) // И здесь тоже const obj = {} console.log(obj.forEach) // undefined, потому что у объектов нет такого метода
На практике
Секция статьи «На практике»Егор Огарков советует
Секция статьи «Егор Огарков советует»🛠 Имена аргументов в функции-колбэке можно давать любые, главное, чтобы код было удобно читать.
🛠 Три параметра в функции-колбэке позволяют проводить дополнительные проверки. Например, последний ли это элемент массива:
const nums = [1, 2, 3, 4, 5]nums.forEach((num, index, arr) => { // Добавим к первому числу 9 if (index === 0) { num = num + 9 } // А последнее умножим на 2 else if (index === arr.length - 1) { num = num * 2 } console.log(num)})
const nums = [1, 2, 3, 4, 5] nums.forEach((num, index, arr) => { // Добавим к первому числу 9 if (index === 0) { num = num + 9 } // А последнее умножим на 2 else if (index === arr.length - 1) { num = num * 2 } console.log(num) })
Выведет:
10 2 3 4 10
8.5 Способы перебора массива в JavaScript | Дэвид Фекке
Фото Себастьяна Кляйна на UnsplashИз моего сообщения в блоге о циклах JavaScript.
Одно из моих любимых выражений: «С кота можно содрать шкуру разными способами». Не поймите меня неправильно, я люблю кошек, но это проиллюстрирует мою точку зрения.
Photo by Linnea Sandbakk on UnsplashJavaScript как язык дает вам много разных способов выполнения одной и той же задачи. Итерация или перебор массива является примером того, что у вас есть много разных способов выполнить одну и ту же задачу.
В этом примере давайте создадим массив из пяти элементов, используя литерал массива. Мы также создадим простую функцию для возврата результатов в консоль.
Оригинальный способ обхода массива в цикле в JavaScript использует традиционный оператор цикла for, который принимает три выражения, за которыми следует оператор.
Первая часть цикла for в скобках определяет инициализатор. Это позволяет циклу for сохранять переменную для отслеживания ее положения в цикле. Вторая часть — условие. Здесь мы сообщаем циклу, что хотим перебирать только этот массив, пока не дойдем до конца. Последняя часть — это финальное выражение, в котором мы увеличиваем единицу до нашего инициализатора. Это значение будет увеличиваться при каждом выполнении оператора.
В этом примере на консоль возвращаются следующие значения в указанном порядке;
2. Цикл for-inFirst
2
3.3
Foo
Bar
Во втором примере мы просто перебираем массив. Переменная перед ключевым словом «in» будет назначать значение индекса для каждого элемента в массиве. Итак, если в нашем массиве пять элементов, он присвоит «индексу» числа «0, 1, 2, 3, 4». Затем мы можем передать это значение в нижнем индексе массива, чтобы получить значение для этой позиции в массиве.
Цикл for-of похож на цикл for-in, но фактически возвращает значение каждого элемента массива.
Как видно из приведенного выше примера, переменной item присваивается фактическое значение массива. Этот же оператор можно также использовать для перебора всех элементов объекта, а также массива.
4. Цикл Do-whileЦикл Do-while подобен исходному циклу for в примере 1, но выражение условия передается в конце оператора.
В четвертом примере выше мы определяем переменную итератора «i» перед нашим циклом. Это не требуется для использования цикла do-while. Нам просто нужно выражение условия, которое можно использовать для выхода из цикла. В этом случае мы увеличиваем 1 до переменной «i» каждый раз, когда оператор выполняется в цикле, а в условии while мы проверяем, чтобы убедиться, что значение «i» меньше длины массива.
Цикл while похож на цикл do-while, но вы устанавливаете выражение условия в начале оператора.
В нашем пятом примере мы устанавливаем переменную j в качестве нашего начального итератора и увеличиваем это значение на единицу в операторе цикла. Условие while проверяет, чтобы значение j было меньше длины массива.
6. Цикл ForEach Метод forEach для прототипа массива был добавлен в версии 5 JavaScript. На самом деле это пример функции высшего порядка или функции, которая принимает другую функцию в качестве параметра. эти типы параметров иногда называют «обратным вызовом». Обратный вызов для метода forEach принимает параметр фактического элемента, который мы итерируем в массиве, но также принимает необязательные параметры для индекса и всего массива.
Вот самый простой способ использования метода forEach для цикла по массиву.
В этом шестом примере мы передаем функцию массива, которая печатает текущий элемент, который повторяется в массиве. Мы также можем сделать это следующим образом;
7. РекурсияJavaScript по своей сути является функциональным языком программирования. Во многих языках функционального программирования способ перебора массива заключается в использовании рекурсии или использовании функции, которая может вызывать сама себя.
В этом седьмом примере мы определили функцию под названием «рекурсивная», которая принимает массив в качестве параметра. Внутри функции мы «сдвигаем» или удаляем один элемент из массива, а затем передаем эту новую версию массива в эту же функцию. У нас есть условие в функции, которое проверяет, что в массиве все еще есть элементы для обработки.
Если вы хотите сохранить исходный массив, вы можете сделать копию массива, используя оператор расширения «…», как в следующем примере;
8.
Еще один способ перебора нашего массива — использование Symbol.iterator.
В восьмом примере мы используем этот итератор Symbol для инициализации объекта итератора. Затем мы можем вызвать метод «следующий» для объекта итератора. Мы можем продолжать вызывать этот итератор до тех пор, пока его свойство «done» не вернет false.
Мы используем оператор do-while, чтобы проверить, когда свойство «done» становится ложным, чтобы завершить выполнение этого итератора.
8.5. ГенераторыГенераторы аналогичны итератору, который мы использовали ранее в восьмом примере. Из-за этого я буду называть этот пример только 8.5. Генераторы определяются с помощью «*» в начале имени функции. Мне лично не нравится, как это используется, потому что, если вы исходите из языка, основанного на «C», это можно спутать с указателем.
В этом последнем примере мы определили функцию генератора с именем myGenerator. Генераторы могут либо возвращать, либо выдавать значение. В этом примере мы вызываем функцию myGenerator для создания объекта-генератора. Объект Generator, как и объект итератора, имеет метод «следующий», который возвращает следующее значение в массиве. Генератор также имеет параметр «выполнено», который мы можем использовать, чтобы определить, завершил ли генератор выполнение.
Здесь мы использовали цикл do-while в качестве выражения для обработки генератора.
РезюмеКак видно из всех этих примеров, есть несколько способов снять шкуру с кота с помощью JavaScript. Только, пожалуйста, не сдирайте кожу с моего кота. 😉
Как перебрать массив в цикле в JavaScript
Циклы широко используются для повторного запуска одного фрагмента кода, каждый раз с другим значением, до тех пор, пока не будет выполнено определенное условие. Они обычно используются для перебора множества значений, вычисления суммы чисел, многократного вызова функции и многого другого.
В этой статье вы узнаете, как использовать циклов JavaScript для перебора элементов массива.
Современный JavaScript поддерживает различные виды циклов:
-
for
— повторяет блок кода заданное количество раз -
forEach()
— выполняет заданную функцию для каждого элемента в массиве или NodeList -
for...in
— Перебирает свойства объекта -
for...of
— перебирает значения итерируемого объекта в цикле -
while
— повторяет блок кода, пока выполняется указанное условие -
do...while
— повторяет блок кода до тех пор, пока определенное условие не станет истинным
for
Цикл Цикл for
используется для перебора массивов и списков узлов в JavaScript. Он имеет следующий синтаксис:
for (инициализация; условие; выражение) { // блок кода, который нужно выполнить }
Как вы можете видеть выше, цикл for
состоит из трех операторов:
-
init
выполняется один раз перед началом выполнения блока кода.Здесь вы определяете, следует ли зациклить весь массив или начать с середины.
-
условие
определяет условие до тех пор, пока цикл не продолжит выполнение блока кода. Это тест, который проверяется после каждой итерации цикла. Если он возвращаетtrue
, цикл продолжит выполнение. Если он возвращаетfalse
, цикл заканчивается. -
expr
выполняется каждый раз после завершения выполнения блока кода. Вы можете использовать этот оператор для увеличения или уменьшения переменной счетчика.
Давайте рассмотрим пример:
const birds = ['🐦', '🦅', '🦆', '🦉'] // зациклить всех птиц for (пусть i = 0; i < birds.length; i++) { console.log(birds[i]) // текущее значение console.log(i) // текущий индекс }
В приведенном выше примере мы используем Оператор init
для установки переменной i
в качестве переменной счетчика. В операторе условие
мы следим за тем, чтобы переменная-счетчик всегда была меньше, чем общее количество элементов массива. Наконец, оператор
expr
просто увеличивает переменную счетчика на 1 каждый раз после завершения выполнения блока кода.
Внутри тела цикла мы можем использовать переменную-счетчик i
для доступа к текущему элементу массива.
forEach()
LoopМетод Array.forEach() был введен в ES6 для однократного выполнения указанной функции для каждого элемента массива в порядке возрастания.
Вот пример, демонстрирующий использование forEach()
для перебора элементов массива в JavaScript:
const birds = ['🐦', '🦅', '🦆', '🦉'] birds.forEach((птица, индекс) => { console.log(`${индекс} -> ${птица}`) }) // 0 -> 🐦 // 1 -> 🦅 // 2 -> 🦆 // 3 -> 🦉
Параметр index
является необязательным. Если не требуется, можете пропустить:
birds.forEach(bird => console.log(bird))
К сожалению, невозможно завершить цикл forEach()
.
for...in
Цикл Оператор for. ..in перебирает свойства объекта.
Вот пример:
const person = { имя: 'Джон Доу', электронная почта: '[email protected]', возраст: 25 } for (const prop in person) { console.log(prop) // имя свойства console.log(person[prop]) // значение свойства }
Оператор for..in
не ограничивается только объектами. Также должно работать для массива (хотя и не рекомендуется):
const digits = [2, 3, 5] for (постоянный индекс в цифрах) { console.log(цифры[индекс]) } // 2 // 3 // 5
for...of
ЦиклОператор for...of появился в ES6. Он перебирает значения итерируемых объектов, таких как массивы, строки, карты, наборы и многое другое.
Вот пример:
const birds = ['🐦', '🦅', '🦉'] // перебираем все значения for (const птица из птиц) { console.log(`Привет, ${птица}`) } // Привет 🐦 // Привет 🦅 // Привет 🦉
Основное различие между операторами for...in
и for.
заключается в том, что первый выполняет итерацию по именам свойств, а второй — по значениям свойств. ..of
Цикл while
Цикл while
выполняет итерацию по кодовому блоку до тех пор, пока выполняется заданное условие. Вот пример:
const cars = ['BMW', 'Porsche', 'Audi', 'Tesla'] пусть я = 0 в то время как (iНе забудьте увеличить значение переменной счетчика
i
. В противном случае цикл никогда не закончится. Вы можете завершить цикломwhile
, используя операторbreak
:while (i < cars.length) { // завершаем, если индекс = 2 если (я === 2) { ломать } // TODO: делайте здесь все, что хотите }Чтобы пропустить итерацию, просто используйте оператор
continue
:while (i < cars.length) { // пропустить 2-ю итерацию если (я === 2) { Продолжать } // TODO: делайте здесь все, что хотите }do.
Цикл..while
Цикл
do...while
аналогичен циклуwhile
. Единственное отличие состоит в том, что циклdo...while
выполняет блок кода по крайней мере один раз перед проверкой условия. Если этоtrue
, блок кода будет повторяться до тех пор, пока условие остаетсяtrue
.Вот пример цикла
do...while
:const cars = ['BMW', 'Porsche', 'Audi', 'Tesla'] пусть я = 0 делать { console.log(i) // индекс console.log(cars[i]) // значение я++ } в то время как (i < cars.length)Точно так же, как
while
, вы можете использовать операторыbreak
иcontinue
для завершения цикла или пропуска итерации.✌️ Понравилась статья? Подписывайтесь на меня Твиттер и LinkedIn. Вы также можете подписаться на Новостная лента.
Знаете ли вы самый быстрый способ перебора массивов, объектов?
Существует несколько способов перебора массива или объектов в JavaScript, но какой из них самый быстрый? Давайте узнаем самый быстрый способ в этой статье.
Массивы
Различные способы мы рассмотрим
- Карта
- ForEach
- For….In
- For…Of
- Цикл For (нормальный/обратный)
- Цикл For с кэшированием длины (нормальный/обратный)
- Цикл while (нормальный/обратный)
- Цикл while с кэшированием длины
ПРИМЕЧАНИЕ. Я использую Node.js replit.com/~
Как мы будем измерять производительность?
Использование перфораторов.
const {производительность} = требуется ('perf_hooks') номера переменных = [] для (var я = 0; я < 1000000; я ++) { числа.push(я) } s1 = производительность.сейчас() for (var iterationNumber = 0; iterationNumber < 10; iterationNumber++){ /* Метод для перебора чисел массива */ } s2 = производительность.сейчас() console.log(`В среднем это заняло ${(s2 - s1)/10} мс`)
- Создать массив из 1 000 000 элементов
- Получить время с помощью performance.
now()
- Перебрать числа массива, используя один из ранее обсуждавшихся методов. Это будет сделано 10 раз.
- Снова получите время с помощью performance.now()
- Найдите разницу во времени и разделите на 10, чтобы получить среднюю продолжительность.
Под перебором массива я подразумеваю доступ к значениям.
Method1: Map
numbers.map( num => num ) /* ВЫХОД В среднем это заняло 16.208858299255372 мс */Method2: ForEach
numbers.forEach( num => num ) /* ВЫХОД В среднем это заняло 10,285145807266236 мс */Метод 3: For..in
for (количество цифр) { число } /* ВЫХОД В среднем это заняло 121,6859667301178 мс */Method4: For….of
for (число чисел) { число } /* ВЫХОД В среднем это заняло 6,2104291915893555 мс */Метод 5: цикл For (нормальный/обратный)
обычный
для (var num = 0; num < numbers.length; num++) { числа [число] } /* ВЫХОД В среднем это заняло 1,6166291236877441 мс */
Обратный
for (var num = number.length; num >= 0 ; num--) { числа [число] } /* ВЫХОД В среднем это заняло 1,717929220199585 мс */Method6: For Loop с кэшированием длины
Normal
const length = number.length for (var num = 0; num < length ; num++) { числа [число] } /* ВЫХОД В среднем ушло 1,5916707992553711 мс */Обратное
const длина = числа.длина for (var num = длина; num >= 0; num--) { числа [число] } /* ВЫХОД В среднем это заняло 1,661899995803833 мс */Method7: цикл While (нормальный/обратный)
обычный
var num = 0 в то время как (число < чисел.длина) { числа [число] число+=1 } /* ВЫХОД В среднем это заняло 1,937641716003418 мс */Обратное
var num = числа.длина в то время как (число > 0) { числа [число] число-=1 } /* ВЫХОД В среднем ушло 1.802162504196167 мс */
Method8: цикл While с кэшированием длины
const length = number.length номер переменной = 0 в то время как (число < длина) { числа [число] число+=1 } /* ВЫХОД В среднем это заняло 1,8967833995819092 мс */Сравнение различных способов перебора массива
Как видите, использование цикла for с кэшированием длины — самый быстрый способ перебора массива. Однако это зависит от браузера (если вы запускаете его в браузере), вашей системы и т. д. Тем не менее, при использовании цикла for/while наблюдается заметный прирост производительности по сравнению с for…in, forEach или map.
Objects
Below are the different ways we will consider
- For…in
- Object.entries
- Object.values
- Object.keys
- Object.getOwnPropertyNames
How will we measure the performance?
Мы используем тот же метод, что и для измерения производительности выше.
Однако вместо массива из 1 000 000 элементов мы будем перебирать объект из 1 000 000 элементов
var Dictionary = {} для (var я = 0; я < 1000000; я ++) { словарь [строка (я)] = я }Под перебором объекта я подразумеваю доступ к значениям.
Метод 1: For….in
for (ключ в словаре){ словарь [ключ] } /* ВЫХОД В среднем это заняло 120,43710422515869 мс */Method2: Object.entries
Object.entries(словарь).forEach( пара => пара[1] ) /* ВЫХОД В среднем это заняло 309,78367910385134 мс */Method3: Object.values
Object.values(словарь).forEach( значение => значение ) /* ВЫХОД В среднем это заняло 15.095704174041748 мс */Method4: Object.keys
Object.keys(словарь).forEach( ключ => словарь[ключ] ) /* ВЫХОД В среднем это заняло 124,35768752098083 мс */Method5: Object.
getOwnPropertyNames
Object.getOwnPropertyNames(словарь).forEach( ключ => словарь[ключ] ) /* ВЫХОД В среднем это заняло 223,96972498893737 мс. */Сравнение различных способов итерации объекта
На изображении выше есть ошибка. В последней строке не должно быть 1,8 мс. Это должно быть 223 мс, как указано в комментариях к коду.
Опять же, производительность может зависеть от различных факторов. Однако при использовании Object.values наблюдается заметный прирост производительности по сравнению с Object.entries
Свяжитесь со мной в LinkedIn, Twitter
Интересно, сколько мой блог заработал в прошлом месяце 💵 или насколько вырос мой блог за последний месяц 📈 ? Или, может быть, вы просто хотите посмотреть на некоторые мемы, подобные этим? Или вы хотите узнать о некоторых интересных репозиториях GitHub? В любом случае подписывайтесь на мою рассылку 📰.