Чисті JavaScript-функції як альтернатива Lodash

5 хв. читання

У статті оглянемо найпопулярніші функції бібліотек Lodash/Underscore.js та їх аналоги серед чистих JS-функцій ES5, ES6.

Поговоримо також про функціональне програмування, яке лежить в основі згаданих бібліотек.

Що таке функціональне програмування

Чисті JavaScript-функції як альтернатива Lodash
Функціональне програмування

Існує багато визначень та пояснень функціонального програмування, ми наведемо стисле:

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

Ключовий момент тут — ваші функції не повинні мати сторонніх ефектів. Так їх легше тестувати, підтримувати та передбачати їх поведінку.

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

1. find

Почнемо саме з цієї поширеної функції. Знайдемо перший елемент колекції, що задовольняє умову.


const users = [
  { 'user': 'joey',  'age': 32 },
  { 'user': 'ross',    'age': 41 },
  { 'user': 'chandler', 'age': 39 }
]

// Нативна функція
users.find(function (o) { return o.age < 40; })

// lodash
_.find(users, function (o) { return o.age < 40; })

Порівняємо продуктивність обох функцій.

Чисті JavaScript-функції як альтернатива Lodash
Нативний find продуктивніший за _.find від Lodash

Ви можете оглянути код з тестовими і власними даними за посиланням.

Не варто думати, що нативні функції завжди продуктивніші за аналоги в Lodash. Є досить складні функції, які ми реалізуємо менш продуктивно, ніж у бібліотеці. Але якщо нативна функція проста та більш читабельна, варто розглядати її як гарну альтернативу.

2. filter

array.filter допомагає отримати усі елементи колекції, які задовольняють певну умову.

const numbers = [10, 40, 230, 15, 18, 51, 1221]       

_.filter(numbers, num => num % 3 === 0)
numbers.filter(num => num % 3 === 0)
Чисті JavaScript-функції як альтернатива Lodash
Порівняння продуктивності filter

Порівняйте продуктивність методів.

3. first and rest

Існує безліч ситуацій, коли вам треба отримати перший елемент з колекції, а решту зберегти в масив.

const names = ["first", "middle", "last", "suffix"]

const firstName = _.first(names) 
const otherNames = _.rest(names) 

const [firstName, ...otherNames] = names
console.log(firstName) // 'first'
console.log(otherNames) // [ 'middle', 'last', 'suffix' ]

Імовірно, ви використовували spread-оператор (...) для інших випадків. Тут ми використовуємо його для деструктурування елементів масиву.

Порівняння продуктивності між first та rest залишаємо на читача.

4. each

Вам краще використовувати «ванільний» цикл for, ніж будь-які вбудовані ітератори. Це той самий випадок, коли функції lodash мають перевагу у продуктивності.


_.each([1, 2, 3], (value, index) => {
  console.log(value)
})

[1, 2, 3].forEach((value, index) => {
  console.log(value)
})

_.forEach({ 'a': 1, 'b': 2 }, (value, key) => {
  console.log(key);
});

({ 'a': 1, 'b': 2 }).forEach((value, key) => { // !помилка
  console.log(key); 
});

Результати тесту виходять цікавими:

Чисті JavaScript-функції як альтернатива Lodash
_.each — беззаперечний переможець

each від Lodash набагато швидший, адже його реалізація особлива для кожного браузеру.

Розробники Lodash пояснюють, що відносна швидкість нативного forEach відрізняється залежно від браузера. Хоч forEach нативний, це ще не означає, що він швидший за звичайний цикл for чи while. По-перше, forEach має справу з більш особливими випадками. По-друге, forEach використовує колбеки, а це потенційні додаткові витрати на виклик функцій.

5. every

Функція every перевіряє, чи всі елементи у масиві задовольняють певну умову. Тут нативна реалізація значно швидша.

const elements = ["cat", "dog", "bat"]

_.every(elements, el => el.length == 3)

elements.every(el => el.length == 3) //true
Чисті JavaScript-функції як альтернатива Lodash
_.every vs array.every

Порівняйте продуктивність методів тут.

6. some

Функція some перевіряє, щоб хоча б один елемент масиву задовольняв певну умову.

const elements = ["cat", "dog", "bat"]

_.some(elements, el => el.startsWith('c'))

elements.some(el => el.startsWith('c'))
Чисті JavaScript-функції як альтернатива Lodash
array.some vs _.some

Порівняйте продуктивність методів.

7. includes

Метод перевіряє, чи є елемент у колекції.

const primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,97]

_.includes(primes, 47)

primes.includes(79)
Чисті JavaScript-функції як альтернатива Lodash
array.includes vs _.includes

Порівняйте продуктивність методів тут.

8. uniq

Знаходить унікальні елементи масиву.

var elements = [1,2,3,1,2,4,2,3,5,3]

_.uniq(elements)

[...new Set(elements)]

Використаємо прийом зі структурою даних Set, а також spread-оператор для перетворення сету в масив. Тепер перевіримо, як впливатимуть на продуктивність такі маніпуляції.

Чисті JavaScript-функції як альтернатива Lodash
_.uniq набагато продуктивніший

Порівняйте продуктивність методів.

Існує ще кращий спосіб відфільтрувати елементи:

elements.filter((v, i, a) => a.indexOf(v) === i) // definition: filter(callback(value, index, array)

Використовувати нативні функції або їх аналоги з Lodash — вирішувати вам.

9. compact

compact — корисна функція для видалення хибних значень або undefined з масиву.

var array = [undefined, 'cat', false, 434, '', 32.0]
_.compact(array)
array.filter(Boolean)

Тут помічаємо трохи синтаксичного цукру, адже треба перетворити кожен елемент у Boolean, використовуючи array.filter(Boolean), та повернути усі правдиві значення.

Висновок

Так на декількох прикладах ми визначили, на що треба звертати увагу при виборі нативної функції замість бібліотечної. Ось дві головні умови:

  1. Чи можете ви дозволити собі додати зовнішню бібліотеку в застосунок? Варто пам'ятати, що за допомогою таких технік як tree-shaking ви можете додавати лише використовувані модулі. Але чи будете ви готові використовувати зовнішню функцію?
  2. Чи готові ви пожертвувати читабельністю коду заради продуктивності?
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.7K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація