Моя проблема с lodash.js

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

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

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

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

Назначать

Я обнаружил, что лучший пример использования оператора распространения — это функция lodash _.assign(). По сути, функция присваивает все значения одного объекта другому:

let prop1 = { b: "Some property", d: null };
let prop2 = { a: [2, 3], c: "An amazing String", d: 777 };
let prop3 = { a: 888 };
let prop4 = { a: 999 };
const finalProp = _.assign(prop1, prop2, prop3, prop4); console.log(finalProp);
// ==> { a: 999, b: 'Some property', d: 777, c: 'An amazing String'}

Несомненно, это чрезвычайно полезная функция. Однако он очень легко воспроизводим и в большинстве случаев не требует от нас импорта lodash:

const finalProp = { ...prop1, ...prop2, ...prop3, ...prop4 };
console.log(finalProp);
// ==> { a: 999, b: 'Some property', d: 777, c: 'An amazing String' }

Первый метод может показаться более удобным, особенно если вы уже знакомы с функцией assign(). Однако для стиля есть веские причины использовать второй метод:

  1. Дополнительных функций нет, что делает файл более читабельным. Используется только простой JavaScript.
  2. Это устраняет двусмысленность того, что происходит в функции assign, которая может сделать что-то, чего программист не ожидает.
  3. Вы ничего не импортируете в файл.

Это также намного эффективнее: запуск двух функций в двух отдельных файлах (n = 10) занимает в среднем 3.290ms для пользовательской функции, тогда как метод lodash занимает в среднем 4.218ms. Таким образом, пользовательская функция на 28% эффективнее, чем функция lodash.

Союз

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

const _ = require("lodash");
const array1 = [1, 4, "hello", 2, 999];
const array2 = [2, "there", 4.7, "hello"];
console.time();
const finalArray = _.union(array1, array2);
console.timeEnd();
// console.log(finalArray);
// ==> [ 1, 4, 'hello', 2, 999, 'there', 4.7 ]

Используя те же объекты, мы можем просто использовать

const finalArray = new Set([...array1, ...array2]);

чтобы получить тот же результат, опять же с повышенной эффективностью (0.578ms для lodash, 0.107ms для внутренних, на 540 % эффективнее). В дополнение к этому, также намного яснее, что именно происходит, когда написано явно.

Клон & CloneDeep

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

let pocket = ["phone", "wallet"];
let anotherPocket = pocket;
pocket.push("keys");
console.log(pocket === anotherPocket);
// ==> true

Если нам не повезло с решением, которое мы нашли, или если мы поспешили с обучением (как я), то мы, вероятно, выучили решение lodash, которое дублирует любой объект, заданный функцией:

const _ = require("lodash");
let suitcase = { clothes: true };
let vacationItems = { tripleTap: true, bag: suitcase };
const vacationItemsClone = _.clone(vacationItems);

Хотя это решение выполняет работу по созданию поверхностной копии данного объекта, мне в среднем потребовалось около 0.611ms, чтобы клонировать этот элемент. На мой взгляд, лучшим решением является то, которое снова использует оператор распространения:

let suitcase = { clothes: true };
let vacationItems = { tripleTap: true, bag: suitcase };
const vacationItemsClone = { ...vacationItems };

Оператор спреда помогает нам добиться того же результата, принимая только 0.105ms. Это в 5,8 раза (на 581% эффективнее) быстрее, чем функция lodash! Другой, похожий способ клонирования дает примерно такие же сроки. Конечно, приведенные объекты очень просты, и, вероятно, есть примеры, в которых мое решение не работает. В противном случае в функции lodash больше не было бы необходимости.

Но как насчет глубокого клонирования объекта, чтобы ссылки на внутренние объекты также клонировались? Для этого lodash делает очень чистую, но опять же неэффективную работу:

const _ = require("lodash");
let suitcase = { clothes: true };
let vacationItems = { tripleTap: true, bag: suitcase }; console.time();
const vacationItemsDeepClone = _.cloneDeep(vacationItems);

На моем Mac эта функция занимает в среднем 0.985ms, тогда как моя пользовательская функция занимает только 0.197ms (на 500 % эффективнее):

let suitcase = { clothes: true };
let vacationItems = { tripleTap: true, bag: suitcase };
console.time();
const vacationItemsDeepClone = JSON.parse(
    JSON.stringify(vacationItems)
);
console.timeEnd();

Ясно, что это гораздо более сложная функция, чем простая функция cloneDeep() из lodash, поэтому я до сих пор использую cloneDeep() из lodash. Я признаю, что функция lodash не особенно эффективна, но она делает код более читабельным, и вам не придется беспокоиться о том, что класс JSON попытается преобразовать в строку и проанализировать очень большой объект.

Вывод

Lodash — отличная библиотека с множеством ресурсов. Я часто использовал функции lodash, такие как разность() или isEqual(). Однако я утверждаю, что чрезмерное использование lodash, особенно для некоторых функций, которые я упомянул, может оказать негативное влияние на ваш проект. Наличие кода, состоящего из множества различных функций lodash, требует от новых разработчиков изучения пакета, а не JavaScript, что требует времени и усилий. Использование библиотечных функций там, где подойдут более простые функции, снизит понимание любого данного языка программирования, что со временем снизит эффективность кодирования.

Первоначально опубликовано на http://github.com.