本帖最后由 断天涯大虾 于 2017-3-20 10:32 编辑
到目前为止, 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]
- // 替代成
- [1, 2, 3].map(n => n * 3);
- [1, 2, 3].reduce((total, n) => total + n);
- [1, 2, 3].filter(n => n <= 2);
复制代码
2. Head & Tail解构语法 允许我们获取无效果函数返回列表的头部和尾部。 - _.head([1, 2, 3]);
- // 1
- _.tail([1, 2, 3]);
- // [2, 3]
- // 替代成
- const [head, ...tail] = [1, 2, 3];
复制代码我们还能以类似的方式获得初始元素(译者注:最后一个元素之前的元素)和最后一个元素。 - _.initial([1, 2, 3]);
- // -> [1, 2]
- _.last([1, 2, 3]);
- // 3
- // 替代成
- const [last, ...initial] = [1, 2, 3].reverse();
复制代码如果你觉得反向变化数据结构很烦人,你还可以在调用 reverse 之前使用spread操作符来克隆数组。 - const xs = [1, 2, 3];
- const [last, ...initial] = [...xs].reverse();
复制代码
3. Rest & Spreadrest 和 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"
- // 替换成
- 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"
复制代码没有像 TypeScript 或 Flow 这样的高级语言,我们就不能给函数类型签名,这样使得 currying 相当困难。当我们传入已curry过的函数时,很难知道已经提供了多少参数,下一步需要提供哪些参数。使用箭头函数,我们可以显式的定义已curry过的函数,使其他程序员更容易理解。 - function add(a, b) {
- return a + b;
- }
- var curriedAdd = _.curry(add);
- var add2 = curriedAdd(2);
- add2(1);
- // 3
- // 替换成
- const add = a => b => a + b;
- const add2 = add(2);
- add2(1);
- // 3
复制代码这些已curry过的箭头函数对于调试尤其重要。 - var lodashAdd = _.curry(function(a, b) {
- return a + b;
- });
- var add3 = lodashAdd(3);
- console.log(add3.length)
- // 0
- console.log(add3);
- //function wrapper() {
- // var length = arguments.length,
- // args = Array(length),
- // index = length;
- //
- // while (index--) {
- // args[index] = arguments[index];
- // }…
- // 替换成
- const es6Add = a => b => a + b;
- const add3 = es6Add(3);
- console.log(add3.length);
- // 1
- console.log(add3);
- // function b => a + b
复制代码- _.map(_.prop('name'))(people);
- // 替换成
- people.map(person => person.name);
复制代码
5. Partial像应用于curry这样,我们也可以利用箭头函数使partical应用变得容易和明确。 - var greet = function(greeting, name) {
- return greeting + ' ' + name;
- };
- var sayHelloTo = _.partial(greet, 'hello');
- sayHelloTo('fred');
- // "hello fred"
- // 替换成
- const sayHelloTo = name => greet('hello', name);
- sayHelloTo('fred');
- // "hello fred"
复制代码还可以传入带有spread操作符的rest参数来部分应用可变函数 - const sayHelloTo = (name, ...args) => greet('hello', name, ...args);
- sayHelloTo('fred', 1, 2, 3);
- // "hello fred"
复制代码
6. OperatorsLodash提供了许多函数,将函数重新实现为语法操作符,这样就可以将它们传递给集合方法。 在大多数情况下,箭头函数能以足够简短的行内调用实现同样的效果,
- _.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
- // 替换成
- 3 === 3
- 10 + 1
- [1, 2, 3].map(n => n * 10
- [1, 2, 3].reduce((total, n) => total + n);
复制代码
7. Paths许多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']
- //替换成
- [
- 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 }
- // 替换成
- const { a, c } = { a: 1, b: 2, c: 3 };
- return { a, c };
复制代码
9. Constant,Identity,NoopLodash提供了一些实用函数,这些函数可以用于创建具有特定行为的简单函数。 - _.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. Chaining & FlowLodash提供了一些帮助我们编写链接语句的函数。在多数情况一下,内置的集合方法可以返回一个可以直接链接的数组实例,但是在某些情况下,集合方法会有问题。 但是,我们可以通过一个箭头函数数组定义相同的变换。 - _([1, 2, 3])
- .tap(function(array) {
- // Mutate input array.
- array.pop();
- })
- .reverse()
- .value();
- // [2, 1]
- // 替换成
- const pipeline = [
- array => { array.pop(); return array; },
- array => array.reverse()
- ];
- pipeline.reduce((xs, f) => f(xs), [1, 2, 3]);
复制代码这样,我们甚至不必去思考tap和thru之间的区别。在实用函数中包含这个reduction,使之成为一个通用的工具。 - 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终归是一个强大的库,本文只是提供了一个新的视角,以前依赖Lodash实用工具模块的情况下解决的一些问题,如何使用JavaScript演变版本来解决。 不要忽视这些,而是下次你完成一个抽象时,想想是不是一个简单的函数就可以解决问题。
|