Главная » Статьи » 10 функций Lodash, которые можно заменить на ES6

10 функций Lodash, которые можно заменить на ES6

10 функций Lodash, которые можно заменить на ES6

От автора: на данный момент Lodash – самый зависимый от npm пакет, но, если вы будете использовать ES6 функции, он вам может не понадобиться. В этой статье мы рассмотрим нативные методы сбора со стрелочными функциями и другими функциями ES6, которые помогут нам в большинстве популярных случаев использования.

1. Map, Filter, Reduce

Эти методы сбора упрощают трансформацию данных и имеют универсальную поддержку. Их можно совмещать со стрелочными функциями, что позволяет писать маленькие альтернативы реализациям Lodash:

_.map([1, 2, 3], function(n) { return n * 3; });
// [3, 6, 9]
_.reduce([1, 2, 3], function(total, n) { return total + n; }, 0);
// 6
_.filter([1, 2, 3], function(n) { return n <= 2; });
// [1, 2] // becomes [1, 2, 3].map(n => n * 3);
[1, 2, 3].reduce((total, n) => total + n);
[1, 2, 3].filter(n => n <= 2);

Но это не все. В современных браузерах можно использовать find, some, every и reduceRight.

2. Head и Tail

Синтаксис деструктуризации позволяет получать начало и оставшуюся часть списка без функций-утилит:

_.head([1, 2, 3]);
// 1
_.tail([1, 2, 3]);
// [2, 3] // becomes const [head, ...tail] = [1, 2, 3];

Точно так же можно получить последний элемент и оставшиеся:

_.initial([1, 2, 3]);
// -> [1, 2]
_.last([1, 2, 3]);
// 3 // becomes const [last, ...initial] = [1, 2, 3].reverse();

Если вас бесит, что reverse мутирует структуру данных, можете использовать оператор расширения для клонирования массива перед вызовом reverse:

const xs = [1, 2, 3];
const [last, ...initial] = [...xs].reverse();

3. Rest и Spread

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

var say = _.rest(function(what, names) { var last = _.last(names); var initial = _.initial(names); var finalSeparator = (_.size(names) > 1 ? ', & ' : ''); return what + ' ' + initial.join(', ') + finalSeparator + _.last(names);
}); say('hello', 'fred', 'barney', 'pebbles');
// "hello fred, barney, & pebbles" // becomes const say = (what, ...names) => { const [last, ...initial] = names.reverse(); const finalSeparator = (names.length > 1 ? ', &' : ''); return `${what} ${initial.join(', ')} ${finalSeparator} ${last}`;
}; say('hello', 'fred', 'barney', 'pebbles');
// "hello fred, barney, & pebbles"

4. Curry

Без языка более высокого уровня типа TypeScript или Flow мы не можем дать нашим функциям подписи типов, что усложняет каррирование. При получении каррированной функции сложно определить, сколько аргументов уже было передано и какие необходимо передать далее. С помощью стрелочных функций можно явно определять каррированные функции, что поможет другим разработчикам их понять:

function add(a, b) { return a + b;
}
var curriedAdd = _.curry(add);
var add2 = curriedAdd(2);
add2(1);
// 3 // becomes const add = a => b => a + b;
const add2 = add(2);
add2(1);
// 3

Явные каррированные стрелочные функции в частности важны для отладки:

var lodashAdd = _.curry(function(a, b) { return a + b;
});
var add3 = lodashAdd(3);
console.log(add3.length)
// 0
console.log(add3);
// function (a, b) {
// /* [wrapped with _.curry & _.partial] */
// return a + b;
// } // becomes const es6Add = a => b => a + b;
const add3 = es6Add(3);
console.log(add3.length);
// 1
console.log(add3);
// function b => a + b

Если использовать функциональную библиотеку типа lodash/fp или ramda, можно убрать стиль auto-curry с помощью стрелок:

_.map(_.prop('name'))(people); // becomes people.map(person => person.name);

5. Partial

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

var greet = function(greeting, name) { return greeting + ' ' + name;
}; var sayHelloTo = _.partial(greet, 'hello');
sayHelloTo('fred');
// "hello fred" // becomes const sayHelloTo = name => greet('hello', name);
sayHelloTo('fred');
// "hello fred"

Остальные параметры можно поместить в оператор расширения, чтобы частично применить вариационные функции:

const sayHelloTo = (name, ...args) => greet('hello', name, ...args);
sayHelloTo('fred', 1, 2, 3);
// "hello fred"

6. Операторы

В Lodash есть ряд функций, которые заново реализуют синтаксические операторы в виде функций. То есть их можно передать в методы сбора.

В большинстве случаев стрелочные функции делают их короткими и простыми настолько, что их можно объявить инлайн:

_.eq(3, 3);
// true
_.add(10, 1);
// 11
_.map([1, 2, 3], function(n) { return _.multiply(n, 10);
});
// [10, 20, 30]
_.reduce([1, 2, 3], _.add);
// 6 // becomes 3 === 3
10 + 1
[1, 2, 3].map(n => n * 10);
[1, 2, 3].reduce((total, n) => total + n);

7. Пути

Многие функции Lodash принимают пути в виде строк или массивов. С помощью стрелочных функций можно создавать повторно используемые пути:

var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; _.at(object, ['a[0].b.c', 'a[1]']);
// [3, 4]
_.at(['a', 'b', 'c'], 0, 2);
// ['a', 'c'] // becomes [ obj => obj.a[0].b.c, obj => obj.a[1]
].map(path => path(object)); [ arr => arr[0], arr => arr[2]
].map(path => path(['a', 'b', 'c']));

Так как эти пути это лишь функции, мы можем их записать:

const getFirstPerson = people => people[0];
const getPostCode = person => person.address.postcode;
const getFirstPostCode = people => getPostCode(getFirstPerson(people));

Можно даже сделать пути более высокого порядка с принимаемыми параметрами:

const getFirstNPeople = n => people => people.slice(0, n); const getFirst5People = getFirstNPeople(5);
const getFirst5PostCodes = people => getFirst5People(people).map(getPostCode);

8. Pick

Утилита pick позволяет выбирать свойства из объекта. Это можно сделать и с помощью деструктуризации и сокращенных литералов объектов:

var object = { 'a': 1, 'b': '2', 'c': 3 }; return _.pick(object, ['a', 'c']);
// { a: 1, c: 3 } // becomes const { a, c } = { a: 1, b: 2, c: 3 }; return { a, c };

9. Constant, Identity, Noop

В Lodash есть утилиты для создания простых функций с определенным поведением:

_.constant({ 'a': 1 })();
// { a: 1 }
_.identity({ user: 'fred' });
// { user: 'fred' }
_.noop();
// undefined

Все эти функции можно определить инлайн с помощью стрелок:

const constant = x => () => x;
const identity = x => x;
const noop = () => undefined;

Или можно переписать пример сверху:

(() => ({ a: 1 }))();
// { a: 1 }
(x => x)({ user: 'fred' });
// { user: 'fred' }
(() => undefined)();
// undefined

10. Сцепка и поток

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

Такую же трансформацию можно задать через массив стрелочных функций:

_([1, 2, 3]) .tap(function(array) { // Mutate input array. array.pop(); }) .reverse() .value();
// [2, 1] // becomes const pipeline = [ array => { array.pop(); return array; }, array => array.reverse()
]; pipeline.reduce((xs, f) => f(xs), [1, 2, 3]);

Так нам даже не нужно думать о разнице между tap и thru. Обернув это сокращение в функцию-утилиту, мы создаем отличный инструмент общего назначения:

const pipe = functions => data => { return functions.reduce( (value, func) => func(value), data );
}; const pipeline = pipe([ x => x * 2, x => x / 3, x => x > 5, b => !b
]); pipeline(5);
// true
pipeline(20);
// false

Заключение

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

Автор: Dan Prince

Источник: https://www.sitepoint.com/

Редакция: Команда webformyself.