找回密码
 立即注册

QQ登录

只需一步,快速开始

断天涯大虾
社区贡献组   /  发表于:2017-3-20 10:24  /   查看:5320  /  回复:0
本帖最后由 断天涯大虾 于 2017-3-20 10:32 编辑

到目前为止, Lodash 成为必备的Npm包,但是如果你正在使用ES6,那么你就不一定要使用它。在本文中,我们将使用带箭头函数的本地集合方法和其他新的ES6功能,来帮忙我们实现许多流行的用例。


1. Map,Filter,Reduce
这些集合方法使数据操作变得轻而易举,并且这些方法得到了广泛的支持,我们可以使用这些方法配合箭头函数,来编写一些替代方案来替代Lodash提供的实现。
  1. _.map([1, 2, 3], function(n) { return n * 3; });
  2. // [3, 6, 9]
  3. _.reduce([1, 2, 3], function(total, n) { return total + n; }, 0);
  4. // 6
  5. _.filter([1, 2, 3], function(n) { return n <= 2; });
  6. // [1, 2]
  7. // 替代成
  8. [1, 2, 3].map(n => n * 3);
  9. [1, 2, 3].reduce((total, n) => total + n);
  10. [1, 2, 3].filter(n => n <= 2);
复制代码
它能做的不止这些,如果我们使用ES6 polyfill,我们也可以使用 find , some , everyreduceRight



2. Head & Tail
解构语法 允许我们获取无效果函数返回列表的头部和尾部。
  1. _.head([1, 2, 3]);
  2. // 1
  3. _.tail([1, 2, 3]);
  4. // [2, 3]
  5. // 替代成
  6. const [head, ...tail] = [1, 2, 3];
复制代码
我们还能以类似的方式获得初始元素(译者注:最后一个元素之前的元素)和最后一个元素。
  1. _.initial([1, 2, 3]);
  2. // -> [1, 2]
  3. _.last([1, 2, 3]);
  4. // 3
  5. // 替代成
  6. const [last, ...initial] = [1, 2, 3].reverse();
复制代码
如果你觉得反向变化数据结构很烦人,你还可以在调用 reverse 之前使用spread操作符来克隆数组。
  1. const xs = [1, 2, 3];
  2. const [last, ...initial] = [...xs].reverse();
复制代码



3. Rest & Spread
restspread 函数允许我们定义和调用参数数量可变的函数。ES6引入这两种操作的专用语法。
  1. var say = _.rest(function(what, names) {
  2.   var last = _.last(names);
  3.   var initial = _.initial(names);
  4.   var finalSeparator = (_.size(names) > 1 ? ', & ' : '');
  5.   return what + ' ' + initial.join(', ') +
  6.     finalSeparator + _.last(names);
  7. });

  8. say('hello', 'fred', 'barney', 'pebbles');
  9. // "hello fred, barney, & pebbles"

  10. // 替换成
  11. const say = (what, ...names) => {
  12.   const [last, ...initial] = names.reverse();
  13.   const finalSeparator = (names.length > 1 ? ', &' : '');
  14.   return `${what} ${initial.join(', ')} ${finalSeparator} ${last}`;
  15. };

  16. say('hello', 'fred', 'barney', 'pebbles');
  17. // "hello fred, barney, & pebbles"
复制代码
没有像 TypeScriptFlow 这样的高级语言,我们就不能给函数类型签名,这样使得 currying 相当困难。当我们传入已curry过的函数时,很难知道已经提供了多少参数,下一步需要提供哪些参数。使用箭头函数,我们可以显式的定义已curry过的函数,使其他程序员更容易理解。
  1. function add(a, b) {
  2.   return a + b;
  3. }
  4. var curriedAdd = _.curry(add);
  5. var add2 = curriedAdd(2);
  6. add2(1);
  7. // 3

  8. // 替换成
  9. const add = a => b => a + b;
  10. const add2 = add(2);
  11. add2(1);
  12. // 3
复制代码
这些已curry过的箭头函数对于调试尤其重要。
  1. var lodashAdd = _.curry(function(a, b) {
  2.   return a + b;
  3. });
  4. var add3 = lodashAdd(3);
  5. console.log(add3.length)
  6. // 0
  7. console.log(add3);
  8. //function wrapper() {
  9. //  var length = arguments.length,
  10. //  args = Array(length),
  11. //  index = length;
  12. //
  13. //  while (index--) {
  14. //    args[index] = arguments[index];
  15. //  }…

  16. // 替换成

  17. const es6Add = a => b => a + b;
  18. const add3 = es6Add(3);
  19. console.log(add3.length);
  20. // 1
  21. console.log(add3);
  22. // function b => a + b
复制代码
如果我们在使用像 lodash/fpramda 这样的函数库,还可以使用箭头函数来代替自调用curry的这种方式。
  1. _.map(_.prop('name'))(people);
  2. // 替换成
  3. people.map(person => person.name);
复制代码



5. Partial
像应用于curry这样,我们也可以利用箭头函数使partical应用变得容易和明确。
  1. var greet = function(greeting, name) {
  2.   return greeting + ' ' + name;
  3. };

  4. var sayHelloTo = _.partial(greet, 'hello');
  5. sayHelloTo('fred');
  6. // "hello fred"

  7. // 替换成

  8. const sayHelloTo = name => greet('hello', name);
  9. sayHelloTo('fred');
  10. // "hello fred"
复制代码
还可以传入带有spread操作符的rest参数来部分应用可变函数
  1. const sayHelloTo = (name, ...args) => greet('hello', name, ...args);
  2. sayHelloTo('fred', 1, 2, 3);
  3. // "hello fred"
复制代码



6. Operators
Lodash提供了许多函数,将函数重新实现为语法操作符,这样就可以将它们传递给集合方法。
在大多数情况下,箭头函数能以足够简短的行内调用实现同样的效果,

  1. _.eq(3, 3);
  2. // true
  3. _.add(10, 1);
  4. // 11
  5. _.map([1, 2, 3], function(n) {
  6.   return _.multiply(n, 10);
  7. });
  8. // [10, 20, 30]
  9. _.reduce([1, 2, 3], _.add);
  10. // 6

  11. // 替换成

  12. 3 === 3
  13. 10 + 1
  14. [1, 2, 3].map(n => n * 10
  15. [1, 2, 3].reduce((total, n) => total + n);
复制代码



7. Paths
许多Lodash的函数将路径作为字符串或数组。使用箭头函数可以创建更多可重用的路径。
  1. var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
  2. _.at(object, ['a[0].b.c', 'a[1]']);
  3. // [3, 4]

  4. _.at(['a', 'b', 'c'], 0, 2);
  5. // ['a', 'c']

  6. //替换成
  7. [
  8.   obj => obj.a[0].b.c,
  9.   obj => obj.a[1]
  10. ].map(path => path(object));

  11. [
  12.   arr => arr[0],
  13.   arr => arr[2]
  14. ].map(path => path(['a', 'b', 'c']));
复制代码
因为这些路径"只是函数",我们也可以使它们组合。
  1. const getFirstPerson = people => people[0];
  2. const getPostCode = person => person.address.postcode;
  3. const getFirstPostCode = people => getPostCode(getFirstPerson(people));
复制代码
我们甚至可以创建可接收参数的高阶路径。
  1. const getFirstNPeople = n => people => people.slice(0, n);

  2. const getFirst5People = getFirstNPeople(5);
  3. const getFirst5PostCodes = people => getFirst5People(people).map(getPostCode);
复制代码



8. Pick
实用函数 pick 允许我们从目标对象中选择我们想要的属性。我们可以使用解构和简略的对象字面量实现相同的结果。
  1. var object = { 'a': 1, 'b': '2', 'c': 3 };

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

  4. // 替换成
  5. const { a, c } = { a: 1, b: 2, c: 3 };
  6. return { a, c };
复制代码



9. Constant,Identity,Noop
Lodash提供了一些实用函数,这些函数可以用于创建具有特定行为的简单函数。
  1. _.constant({ 'a': 1 })();
  2. // { a: 1 }
  3. _.identity({ user: 'fred' });
  4. // { user: 'fred' }
  5. _.noop();
  6. // undefined
复制代码
我们可以使用箭头函数通过内联方式定义这些函数
  1. const constant = x => () => x;
  2. const identity = x => x;
  3. const noop = () => undefined;
复制代码
或者我们可以重写上面的例子:
  1. (() => ({ a: 1 }))();
  2. // { a: 1 }
  3. (x => x)({ user: 'fred' });
  4. // { user: 'fred' }
  5. (() => undefined)();
  6. // undefined
复制代码



10. Chaining & Flow
Lodash提供了一些帮助我们编写链接语句的函数。在多数情况一下,内置的集合方法可以返回一个可以直接链接的数组实例,但是在某些情况下,集合方法会有问题。
但是,我们可以通过一个箭头函数数组定义相同的变换。
  1. _([1, 2, 3])
  2. .tap(function(array) {
  3.    // Mutate input array.
  4.    array.pop();
  5. })
  6. .reverse()
  7. .value();
  8. // [2, 1]

  9. // 替换成

  10. const pipeline = [
  11.   array => { array.pop(); return array; },
  12.   array => array.reverse()
  13. ];

  14. pipeline.reduce((xs, f) => f(xs), [1, 2, 3]);
复制代码
这样,我们甚至不必去思考tap和thru之间的区别。在实用函数中包含这个reduction,使之成为一个通用的工具。
  1. const pipe = functions => data => {
  2.   return functions.reduce(
  3.     (value, func) => func(value),
  4.     data
  5.   );
  6. };

  7. const pipeline = pipe([
  8.   x => x * 2,
  9.   x => x / 3,
  10.   x => x > 5,
  11.   b => !b
  12. ]);

  13. pipeline(5);
  14. // true
  15. pipeline(20);
  16. // false
复制代码



总结
Lodash终归是一个强大的库,本文只是提供了一个新的视角,以前依赖Lodash实用工具模块的情况下解决的一些问题,如何使用JavaScript演变版本来解决。
不要忽视这些,而是下次你完成一个抽象时,想想是不是一个简单的函数就可以解决问题。

   
关于葡萄城:全球最大的控件提供商,世界领先的企业应用定制工具、企业报表和商业智能解决方案提供商,为超过75%的全球财富500强企业提供服务。

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部