Мы все были там как разработчики. У нас есть массив данных, которые нам нужно перебрать. Будучи младшим разработчиком, вы можете не знать, какую встроенную функцию JS использовать. Итак, вы идете в Stackoverflow. Вы видите решения своей проблемы, используя .filter(), .map()а также .forEach(). Но что это? И когда вы действительно должны их использовать? Давай выясним.


.фильтр

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

Давайте рассмотрим правильное использование этой встроенной функции javascript и сравним ее с использованием побочных эффектов.

// Proper Usage
const fruits = ['apple', 'orange', 'kiwi']

const fruitsMinusKiwi = fruits.filter(fruit => {
    return fruit !== 'kiwi'
})
Войти в полноэкранный режим

Выйти из полноэкранного режима

// Improper Usage (Side-effect)
const fruits = ['apple', 'orange', 'kiwi']

fruits.filter(fruit => {
    console.log(fruit)
    return fruit
})
Войти в полноэкранный режим

Выйти из полноэкранного режима

На первый взгляд они кажутся похожими. Кажется, они даже используют одинаковое количество памяти и времени для завершения. Один просто фильтрует массив, а другой просто регистрирует содержимое. Использование, которое регистрирует содержимое, фактически не присваивает никаких значений. Так это нормально, да? Ну нет. Не совсем. Эта функция выполняет дополнительный шаг, пытаясь вернуть значения.

Эта разница, честно говоря, незначительна в большинстве приложений. На самом деле, вам, вероятно, даже не нужно беспокоиться об этом. Однако, если вы когда-либо работали над крупномасштабными приложениями, требующими высокодоступных и производительных ресурсов для тысяч активных конечных пользователей, это абсолютно необходимо.

Смотрите, как набор данных, который мы зацикливаем, увеличивается. Как и наше время завершения. Например, если этот цикл занимает 2 мс для 10 записей при правильном использовании и 3 мс при неправильном использовании. Тогда у вас есть 2 мс и 3 мс соответственно. Однако давайте добавим 10 000 записей для циклического прохождения. Теперь у нас есть 2 секунды и 3 секунды соответственно. Неправильное использование теперь требует на целую секунду больше времени для завершения своего кода.


// Ресурсы и ссылки


.карта

.map очень похож на .filter функция. Однако эта встроенная функция не пытается вернуть новый отфильтрованный массив. Вместо этого эта функция возвращает новый массив со всеми возвращенными данными. Технически вы все еще можете фильтровать, просто ничего не возвращая для текущей итерации.

// Proper Usage
const fruits = ['apple', 'orange', 'kiwi']

const fruitsLowerCased = fruits.map(fruit => {
    return fruit.toLowerCase()
})
Войти в полноэкранный режим

Выйти из полноэкранного режима

// Improper Usage (Side-effect)
const fruits = ['apple', 'orange', 'kiwi']

fruits.map(fruit => {
    console.log(fruit)
})

---
// Improper Usage (pushing to array rather than assign)
const fruits = ['apple', 'orange', 'kiwi']
let fruitsLowerCased = []

fruits.map(fruit => {
    fruitsLowerCased.push(fruit.toLowerCase())
})

Войти в полноэкранный режим

Выйти из полноэкранного режима

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


.для каждого

Эта встроенная функция на самом деле ничего не возвращает. Вместо этого это литерал цикла for, который просто перебирает итерируемый объект и предоставляет каждое значение в обратном вызове. Например:


const fruits = ['apple', 'orange', 'kiwi']

fruits.forEach(fruit => console.log(fruit))
Войти в полноэкранный режим

Выйти из полноэкранного режима

Это очень похоже на:


const fruits = ['apple', 'orange', 'kiwi']

for (let fruit of fruits) {
    console.log(fruit)
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

Оба являются правильными способами перебора объекта без генерации дополнительных данных. Скорее, вы берете уже имеющиеся данные в пространстве памяти и читаете их или манипулируете ими. Например, давайте запишем наши значения в нижнем регистре.

  • Обратите внимание: поскольку они ничего не возвращают (недействительные функции), нам нужна переменная вне области действия цикла для записи наших значений в нижнем регистре.
  • Поэтому их не следует использовать в случае, когда вам нужны данные. Скорее используйте .filter или же .map функция.

const fruits = ['apple', 'orange', 'kiwi']

fruits.forEach(fruit => console.log(fruit.toLowerCase))

---

const fruits = ['apple', 'orange', 'kiwi']

for (let fruit of fruits) {
    console.log(fruit.toLowerCase())
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

Нет


const fruits = ['apple', 'orange', 'kiwi']
let fruitsLowerCased = []

for (let fruit of fruits) {
    fruitsLowerCased.push(fruit.toLowerCase())
}

---

const fruits = ['apple', 'orange', 'kiwi']
let fruitsLowerCased = []

fruits.forEach(fruit => fruitsLowerCased.push(fruit.toLowerCase))

Войти в полноэкранный режим

Выйти из полноэкранного режима

Хорошо. Таким образом, у нас есть понимание того, как они работают и как их использовать. Давайте рассмотрим несколько примеров из реальной жизни. Проверьте пример ниже!


Если вам понравилась эта статья, пожалуйста, оставьте комментарий и поделитесь тем, что вы узнали! Я что-то пропустил? Если это так, пожалуйста, дайте мне знать!