DevGang
Авторизоваться

Обзор технических различий между циклами в JavaScript

При работе с циклами в JavaScript необходимо правильно определить две вещи: enumerable properties и iterable objects.

Перечислимые свойства

Одной из определяющих характеристик перечисляемого объекта является то, что мы устанавливаем внутренний флаг перечисления в true, когда присваиваем свойство объекту с помощью оператора присваивания. Это значение по умолчанию.

Однако мы можем изменить это поведение, установив для него значение false.

Практическое правило заключается в том, что перечислимое свойство всегда отображается в цикле for … in.

Давайте посмотрим на это в действии:

// отображается в цикле for .... in
const gbols = {};
gbols.platform = "LogRocket";

Object.getOwnPropertyDescriptor(gbols, "platform")
{value: "LogRocket", writable: true, enumerable: true, configurable: true}

// не отображается в цикле for .... in 
// для большего контроля над этими свойствами мы используем
Object.defineProperty(gbols, 'role', {value: 'Admin', writable: true, enumerable: false})

// Тестирование результатов для
for (const item in gbols) {
console.log(item)
}
 // регистрирует платформу

Итерируемые объекты

Объект является итеративным, если он определяет свое итерационное поведение. Значение, которое будет зациклено в конструкции for …of, в этом случае будет определять ее итерационное поведение. Встроенные типы, которые являются итерационными, включают в себя ArraysStrings, Sets и Maps в object не является итерационным, так как он не указывает @iterator method.

По сути, в Javascript все итерации являются перечисляемыми, но не все перечисляемые объекты являются итерациями.

Вот способ концептуализировать это: for …in ищет объект в данных, в то время как for ..of ищет повторяющиеся последовательности.

Посмотрим, как это все выглядит при использовании с типом данных Array:

 const authors = ['Jade', 'Dafe', 'Gbols', 'Daniel'];
// использование с циклом
for (const author in authors) {
console.log(author)
}
// записывает 0,1,2,3

for (const author of authors) {
console.log(author)
}
// регистрирует Jade, Dafe, Gbols, Daniel

При использовании этих конструкций следует помнить о том, что если вызывается typeof, и вы получаете ответ object, тогда вы можете использовать цикл for …in.

Давайте посмотрим на эту операцию с авторской переменной:

typeof authors
// регистрирует "объект", поэтому мы можем использовать for ..in

Поначалу это может показаться удивительным, но важно отметить, что массивы - это особый вид объектов с индексами в качестве ключа. Знание того, что for ...in будет искать объект в конструкции, может нам чрезвычайно помочь. Когда цикл for ...in находит объект, он перебирает каждый ключ.

Мы можем визуализировать как for ..in совершает процесс обхода авторских массивов следующим образом:

const authors = {
0: 'Jade',
1: 'Dafe',
2: 'Gbols',
3: 'Daniel'
}

Важное замечание: если его можно отследить до объекта (или унаследовать его от прототипной цепочки объекта), for …in будет выполняться итерацию по ключу в произвольном порядке.

Между тем, если он реализует конструкцию итератора for.. of, он будет перебирать значение на каждой итерации.

ForEach и map методы

Хотя forEach и map методы могут быть использована для достижения тех же вещей, есть различия в их поведении и особенности об их исполнении.

На базовом уровне они оба получают обратный вызов в качестве аргумента при вызове функции.

Рассмотрим следующий фрагмент:

const scoresEach = [2,4 ,8, 16, 32];
const scoresMap = [2,4 ,8, 16, 32];
const square = (num) => num * num;

Давайте перечислим несколько отличий в их работе.

forEach возвращает undefined, а map возвращает новое array:

let newScores = []
const resultWithEach = scoresEach.forEach((score) => {
const newScore = square(score);
newScores.push(newScore);
});
const resultWithMap = scoresMap.map(square);

console.log(resultWithEach) // записывает неопределенный
console.log(resultWithMap) // регистрирует [4, 16, 64, 256, 1024]

Map является чистой функцией, но forEach выполняет некоторую мутацию:  

console.log(newScores) // logs [4, 16, 64, 256, 1024]

На мой взгляд, map отдает предпочтение парадигме функционального программирования. Нам не всегда нужно выполнять мутацию, чтобы получить желаемый результат, в отличие от forEach, где нам приходилось мутировать переменную newScores. При каждом прогоне, когда предоставляется один и тот же ввод, функция map будет давать один и тот же результат. Между тем, аналог forEach возьмет предыдущее значение последней мутации.

Цепочка

Цепочка возможна с map, так как возвращаемый результат - это array. Следовательно, любой другой метод массива может быть немедленно вызван для результата. Другими словами, мы можем назвать filterreducesomeи т.д. Это не возможно с forEach, а возвращаемое значение не определено.

Производительность

Метод map, как правило, работает лучше, чем метод forEach. Вы можете использовать JsPerf для проверки производительности эквивалентного блока кода, реализованного с помощью map и forEach. В среднем вы увидите, что функция map работает как минимум на 50 процентов быстрее.

NB: Этот тест зависит от используемого вами компьютера, а также от реализации вашего браузера.

Вывод

Из всех описанных выше циклических конструкций наиболее управляемым является цикл for..of. Мы можем использовать его с ключевыми словами returncontinue и break. Это означает, что мы можем указать, что мы хотим, чтобы произошло с каждым элементом в array, независимо от того, хотим ли мы уйти пораньше или пропустить.

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

Источник:

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

Оплатив хостинг 25$ в подарок вы получите 100$ на счет

Получить