lodash用法详解以及与ES6的对比
一、讲在前:
1、版本:VERSION = 4.17.5;
2、中文文档:https://www.lodashjs.com/;
3、安装引入:
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lodash.js"></script>
通过 npm:
$ npm i -g npm $ npm i --save lodashimport _ from 'lodash';
二、功能简介
Array
,适用于数组类型,比如填充数据、查找元素、数组分片等操作Collection
,适用于数组和对象类型,部分适用于字符串,比如分组、查找、过滤等操作Function
,适用于函数类型,比如节流、延迟、缓存、设置钩子等操作Lang
,普遍适用于各种类型,常用于执行类型判断和类型转换Math
,适用于数值类型,常用于执行数学运算Number
,适用于生成随机数,比较数值与数值区间的关系Object
,适用于对象类型,常用于对象的创建、扩展、类型转换、检索、集合等操作Seq
,常用于创建链式调用,提高执行性能(惰性计算)String
,适用于字符串类型
lodash/fp
模块提供了更接近函数式编程的开发方式,其内部的函数经过包装,具有 immutable、auto-curried、iteratee-first、data-last(官方介绍)等特点。Lodash 在 GitHub Wiki 中对 lodash/fp 的特点做了如下概述:
Fixed Arity,固化参数个数,便于柯里化
Rearragned Arguments,重新调整参数位置,便于函数之间的聚合
Capped Iteratee Argument,封装 Iteratee 参数
New Methods
三、基本使用对比原生js
1. N 次循环
// 1\. Basic for loop.for(var i = 0; i < 5; i++) { // ...}// 2\. Using Array's join and split methodsArray.apply(null, Array(5)).forEach(function(){ // ...});// Lodash_.times(5, function(){ // ...});
for
语句是执行循环的不二选择,Array.apply
也可以模拟循环,但在上面代码的使用场景下,_.times()
的解决方式更加简洁和易于理解。
2. 深层查找属性值
// Fetch the name of the first pet from each ownervar ownerArr = [{ "owner": "Colin", "pets": [{"name":"dog1"}, {"name": "dog2"}] }, { "owner": "John", "pets": [{"name":"dog3"}, {"name": "dog4"}] }];// Array's map method.ownerArr.map(function(owner){ return owner.pets[0].name; });// Lodash_.map(ownerArr, 'pets[0].name');
_.map
方法是对原生 map
方法的改进,其中使用 pets[0].name
字符串对嵌套数据取值的方式简化了很多冗余的代码,非常类似使用 jQuery 选择 DOM 节点 ul > li > a
,对于前端开发者来说有种久违的亲切感。
3. 个性化数组
// Array's map method.Array.apply(null, Array(6)).map(function(item, index){ return "ball_" + index; });// Lodash_.times(6, _.uniqueId.bind(null, 'ball_'));// Lodash_.times(6, _.partial(_.uniqueId, 'ball_'));// eg. [ball_0, ball_1, ball_2, ball_3, ball_4, ball_5]
在上面的代码中,我们要创建一个初始值不同、长度为 6 的数组,其中 _.uniqueId
方法用于生成独一无二的标识符(递增的数字,在程序运行期间保持独一无二),_partial
方法是对 bind
的封装。
4. 深拷贝
var objA = { "name": "colin"}// Normal method? Too long. See Stackoverflow for solution:// http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript// Lodashvar objB = _.cloneDeep(objA); objB === objA // false
JavaScript 没有直接提供深拷贝的函数,但我们可以用其他函数来模拟,比如 JSON.parse(JSON.stringify(objectToClone))
,但这种方法要求对象中的属性值不能是函数。Lodash 中的 _.cloneDeep
函数封装了深拷贝的逻辑,用起来更加简洁。
5. 随机数
// Naive utility methodfunction getRandomNumber(min, max){ return Math.floor(Math.random() * (max - min + 1)) + min; } getRandomNumber(15, 20);// Lodash_.random(15, 20);
Lodash 的随机数生成函数更贴近实际开发,ECMAScript 的随机数生成函数是底层必备的接口,两者都不可或缺。此外,使用 _.random(15, 20, true)
还可以在 15 到 20 之间生成随机的浮点数。
6. 对象扩展
// Adding extend function to Object.prototypeObject.prototype.extend = function(obj) { for (var i in obj) { if (obj.hasOwnProperty(i)) { this[i] = obj[i]; } } };var objA = {"name": "colin", "car": "suzuki"};var objB = {"name": "james", "age": 17}; objA.extend(objB); objA; // {"name": "james", "age": 17, "car": "suzuki"};// Lodash_.assign(objA, objB);
_.assign
是浅拷贝,和 ES6 新增的 Ojbect.assign
函数功能一致(建议优先使用 Object.assign
)。
7. 筛选属性
// Naive method: Remove an array of keys from objectObject.prototype.remove = function(arr) { var that = this; arr.forEach(function(key){ delete(that[key]); }); };var objA = {"name": "colin", "car": "suzuki", "age": 17}; objA.remove(['car', 'age']); objA; // {"name": "colin"}// LodashobjA = _.omit(objA, ['car', 'age']);// => {"name": "colin"}objA = _.omit(objA, 'car');// => {"name": "colin", "age": 17};objA = _.omit(objA, _.isNumber);// => {"name": "colin"};
大多数情况下,Lodash 所提供的辅助函数都会比原生的函数更贴近开发需求。在上面的代码中,开发者可以使用数组、字符串以及函数的方式筛选对象的属性,并且最终会返回一个新的对象,中间执行筛选时不会对旧对象产生影响。
// Naive method: Returning a new object with selected propertiesObject.prototype.pick = function(arr) { var _this = this; var obj = {}; arr.forEach(function(key){ obj[key] = _this[key]; }); return obj; };var objA = {"name": "colin", "car": "suzuki", "age": 17};var objB = objA.pick(['car', 'age']);// {"car": "suzuki", "age": 17}// Lodashvar objB = _.pick(objA, ['car', 'age']);// {"car": "suzuki", "age": 17}
_.pick
是 _.omit
的相反操作,用于从其他对象中挑选属性生成新的对象。
8. 随机元素
var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];function pickRandomPerson(luckyDraw){ var index = Math.floor(Math.random() * (luckyDraw.length -1)); return luckyDraw[index]; } pickRandomPerson(luckyDraw); // John// Lodash_.sample(luckyDraw); // Colin// Lodash - Getting 2 random item_.sample(luckyDraw, 2); // ['John','Lily']
_.sample
支持随机挑选多个元素并返回心的数组。
9. 针对 JSON.parse 的错误处理
// Using try-catch to handle the JSON.parse errorfunction parse(str){ try { return JSON.parse(str); } catch(e) { return false; } }// With Lodashfunction parseLodash(str){ return _.attempt(JSON.parse.bind(null, str)); } parse('a');// => falseparseLodash('a');// => Return an error objectparse('{"name": "colin"}');// => Return {"name": "colin"}parseLodash('{"name": "colin"}');// => Return {"name": "colin"}
如果你在使用 JSON.parse
时没有预置错误处理,那么它很有可能会成为一个定时炸弹,我们不应该默认接收的 JSON 对象都是有效的。try-catch
是最常见的错误处理方式,如果项目中 Lodash,那么可以使用 _.attmpt
替代 try-catch
的方式,当解析 JSON 出错时,该方法会返回一个 Error
对象。
其中有两处非常值得一看:
// 使用箭头函数创建可复用的路径const object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; [ obj => obj.a[0].b.c, obj => obj.a[1] ].map(path => path(object));// 使用箭头函数编写链式调用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);// truepipeline(20);// false
在 ES6 中,如果一个函数只接收一个形参且函数体是一个 return
语句,就可以使用箭头函数简化为:
const func = p => v;// 类似于(不完全相同)const func = function (p) { return v; }
当有多重嵌套时,可以简化为:
const func = a => b => c => a + b + c; func(1)(2)(3);// => 6// 类似于const func = function (a) { return function (b) { return function (e) { return a + b + c; } } }
四、10 个可用 ES6 替代的 Lodash 特性
原文链接: www.sitepoint.com
中文:https://www.zcfy.cc/article/10-lodash-features-you-can-replace-with-es6-467.html
现在ES6 确实已经大行其道了,但是 lodash 仍然有不可取代的地方。对我而言主要是两点:
1、lodash 的操作(例如 forEach)都是对对象数组都可用的,而 ES6 原生方法往往只对数组有效。
2、lodash 的所有操作都是 null-safe 的,而 ES6 完全不考虑。结果就变成了
const obj={a: {b: {c: {one: 'blue', two: 'red'}}}} _.map(_.get(obj, 'a.b.c'), (item, key)=> item) // ["blue", "red"]
这样的代码想用原生 ES6 实现,就变得繁琐了很多
const obj={a: {b: {c: {one: 'blue', two: 'red'}}}}let tmp = obj && obj.a && obj.a.b && obj.a.b.c tmp && Object.keys(tmp).map(key => tmp[key]) // / ["blue", "red"]
作者:BULL_DEBUG
链接:https://www.jianshu.com/p/5087a09cd6c9
共同学习,写下你的评论
评论加载中...
作者其他优质文章