[关闭]
@xiaoqq 2016-11-10T07:52:03.000000Z 字数 6686 阅读 2216

Lodash学习笔记——与SQL和LINQ的对比

Lodash


零、引言

上次分享听龙哥提起Lodash,就觉得这个框架与C#中的LINQ非常类似,所以,想对比一下两个框架。

LINQ:标准查询运算符,大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable 接口或 IQueryable 接口。标准查询运算符提供了包括筛选、投影、聚合、排序等功能在内的查询功能。

说白了就是可以用写SQL的语句来操作对象集合,LINQ虽然源于SQL,但是却比SQL强大。

而Lodash带给我最惊喜的一点就是,它能类似于LINQ一样直接对JavaScript的数组(Array)、集合(Collection)甚至是对象进行操作。

一、基本查询操作

编程中操作最多的就是查询,一般来说基本查询需要使用到以下六个操作符:

操作 SQL Lodash
查询(投影) select map
过滤 where filter
排序 order by orderBy
分组 group groupBy
连接 join (官方没有)
获取数据 from 每个函数第一个参数/_()/_.chain()

注:在lodash4.0之前,过滤使用的都是selectwhere,4.0之后统一改成了filter

其实JavaScript数组自带的mapfilter函数,已经非常强大了,lodash对其功能基础上进行了两点增强:

  1. 传入的参数不必是函数,可以是字符串(甚至可以不传入参数);
  2. 可以操作对象。

DEMO:

1. Map的使用

  1. var users = {
  2. a:{ 'user': 'barney', 'age': 36, 'active': true },
  3. b:{ 'user': 'fred', 'age': 40, 'active': false },
  4. c:{ 'user': 'pebbles', 'age': 1, 'active': true },
  5. }; //注意,users不是数组,而是一个对象!
  6. _(users).map('age').orderBy().value() //[1, 36, 40]

2. OrderBy的使用

该函数可以输入三个参数,第三个参数使用'asc', 'desc'表示升序还是降序

  1. var users = [
  2. { 'user': 'fred', 'age': 48 },
  3. { 'user': 'barney', 'age': 34 },
  4. { 'user': 'fred', 'age': 40 },
  5. { 'user': 'barney', 'age': 36 }
  6. ];
  7. // Sort by `user` in ascending order and by `age` in descending order.
  8. _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
  9. // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]

3. GroupBy的使用

  1. _(users).groupBy('active').value() //Object {true: Array[2], false: Array[1]}

4. Join的使用

Join是SQL中比较复杂的语句,lodash中也有join函数,但是却不是连接的意思。真正的连接操作要用到一个非官方的库lodash-joins

5. Form是指数据的来源

lodash中每个函数的第一个参数就是输入的数据,当然,也可以使用_()_.chain()包装成一个LodashWrapper对象,最后可以通过链式调用的方式来操作数据。

二、其他常用操作

1. 排序操作

排序:_.orderBy(collection, [iteratees=[_.identity]], [orders])
反转:_.reverse(array)

2. Set操作

去重:_.uniq(array) _.uniqBy(array, [iteratee=_.identity]) _.uniqWith(array, [comparator])还有两个:_.sortedUniq(array) _.sortedUniqBy(array, [iteratee])
交集:_.intersection([arrays]) _.intersectionBy([arrays], [iteratee=_.identity]) _.intersectionWith([arrays], [comparator])
并集:_.union([arrays]) _.unionBy([arrays], [iteratee=_.identity]) _.unionWith([arrays], [comparator])
差集:_.difference(array, [values]) _.differenceBy(array, [values], [iteratee=_.identity]) _.differenceWith(array, [values], [comparator])

3. 过滤操作

过滤:_.filter(collection, [predicate=_.identity])

4. 量词操作

所否所有元素满足: _.every(collection, [predicate=_.identity])
至少一个元素满足:_.some(collection, [predicate=_.identity])
是否包含元素: //TODO 未找到

5. 投影操作

投影:_.map(collection, [iteratee=_.identity]) _.invokeMap(collection, path, [args]) _.mapKeys(object, [iteratee=_.identity]) _.mapValues(object, [iteratee=_.identity])

6. 划分数据

跳过://TODO未找到
提取:_.take(array, [n=1]) _.takeRight(array, [n=1]) _.takeRightWhile(array, [predicate=_.identity]) _.takeWhile(array, [predicate=_.identity])

7. 连接操作

官方文档没有,非官方的库:lodash-joins

8. 分组操作

分组:_.groupBy(collection, [iteratee=_.identity])

9. 删除操作

删除:_.remove(array, [predicate=_.identity])
根据值删除:_.pull(array, [values])

10. 等值操作

等值:_.isEqual(value, other) _.isEqualWith(value, other, [customizer])

11. 元素操作

第一个:_.head(array)
最后一个:_.last(array)
第n个:_.nth(array, [n=0])

12. 串联操作

串联:concat

13. 聚合操作

最大:_.max(array) _.maxBy(array, [iteratee=_.identity])
最小:_.min(array) _.minBy(array, [iteratee=_.identity])
均值:_.mean(array) _.meanBy(array, [iteratee=_.identity])
总和:_.sum(array) _.sumBy(array, [iteratee=_.identity])

三、官方实例

原文链接:Lodash: 10 Javascript Utility Functions That You Should Probably Stop Rewriting

1. Loop for N times

使用times可以让循环更简洁

  1. // 1. Basic for loop.
  2. for(var i = 0; i < 5; i++) {
  3. // ....
  4. }
  5. // 2. Using Array's join and split methods
  6. Array.apply(null, Array(5)).forEach(function(){
  7. // ...
  8. });
  9. // Lodash
  10. _.times(5, function(){
  11. // ...
  12. });

Take note: If your N is going to be non-trivial, please use a basic for loop or a reverse while loop for a much more performant iteration.

2. Loop through a collection and return a deeply-nested property from each item

使用字符串来代替回调函数,这个功能是在惊艳!

  1. // Fetch the name of the first pet from each owner
  2. var ownerArr = [{
  3. "owner": "Colin",
  4. "pets": [{"name":"dog1"}, {"name": "dog2"}]
  5. }, {
  6. "owner": "John",
  7. "pets": [{"name":"dog3"}, {"name": "dog4"}]
  8. }];
  9. // Array's map method.
  10. ownerArr.map(function(owner){
  11. return owner.pets[0].name;
  12. });
  13. // Lodash
  14. _.map(ownerArr, 'pets[0].name');

3. Create an array of N size and populate them with unique values of the same prefix

先来看看uniqueId函数:Generates a unique ID. If prefix is given, the ID is appended to it.

我们要创建一个初始值不同、长度为 6 的数组,其中 _.uniqueId 方法用于生成独一无二的标识符(递增的数字,在程序运行期间保持独一无二)。

  1. // Create an array of length 6 and populate them with unique values. The value must be prefix with "ball_".
  2. // eg. [ball_0, ball_1, ball_2, ball_3, ball_4, ball_5]
  3. // Array's map method.
  4. Array.apply(null, Array(6)).map(function(item, index){
  5. return "ball_" + index;
  6. });
  7. // Lodash
  8. _.times(6, _.uniqueId.bind(null, 'ball_'));

4. Deep-cloning Javascript object

JavaScript 没有直接提供深拷贝的函数,但我们可以用其他函数来模拟,比如 JSON.parse(JSON.stringify(objectToClone)),但这种方法要求对象中的属性值不能是函数。Lodash 中的 _.cloneDeep 函数封装了深拷贝的逻辑,用起来更加简洁。

  1. var objA = {
  2. "name": "colin"
  3. }
  4. // Normal method? Too long. See Stackoverflow for solution: http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
  5. // Lodash
  6. var objB = _.cloneDeep(objA);
  7. objB === objA // false

5. Get Random Number between a range

  1. // Get a random number between 15 and 20.
  2. // Naive utility method
  3. function getRandomNumber(min, max){
  4. return Math.floor(Math.random() * (max - min + 1)) + min;
  5. }
  6. getRandomNumber(15, 20);
  7. // Lodash
  8. _.random(15, 20);

6. Extending object

_.assign 是浅拷贝,和 ES6 新增的 Ojbect.assign 函数功能一致(建议优先使用 Object.assign)。

  1. // Adding extend function to Object.prototype
  2. Object.prototype.extend = function(obj) {
  3. for (var i in obj) {
  4. if (obj.hasOwnProperty(i)) {
  5. this[i] = obj[i];
  6. }
  7. }
  8. };
  9. var objA = {"name": "colin", "car": "suzuki"};
  10. var objB = {"name": "james", "age": 17};
  11. objA.extend(objB);
  12. objA; // {"name": "james", "age": 17, "car": "suzuki"};
  13. // Lodash
  14. _.assign(objA, objB);

7. Removing properties from object

  1. // Naive method: Remove an array of keys from object
  2. Object.prototype.remove = function(arr) {
  3. var that = this;
  4. arr.forEach(function(key){
  5. delete(that[key]);
  6. });
  7. };
  8. var objA = {"name": "colin", "car": "suzuki", "age": 17};
  9. objA.remove(['car', 'age']);
  10. objA; // {"name": "colin"}
  11. // Lodash
  12. objA = _.omit(objA, ['car', 'age']); // {"name": "colin"}

大多数情况下,Lodash 所提供的辅助函数都会比原生的函数更贴近开发需求。在上面的代码中,开发者可以使用数组、字符串以及函数的方式筛选对象的属性,并且最终会返回一个新的对象,中间执行筛选时不会对旧对象产生影响。

8. Select properties from another object to form new object

  1. var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];
  2. function pickRandomPerson(luckyDraw){
  3. var index = Math.floor(Math.random() * (luckyDraw.length -1));
  4. return luckyDraw[index];
  5. }
  6. pickRandomPerson(luckyDraw); // John
  7. // Lodash
  8. _.sample(luckyDraw); // Colin
  9. // Lodash - Getting 2 random item
  10. _.sample(luckyDraw, 2); // ['John','Lily']

9. Selecting a random item from a list

  1. var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];
  2. function pickRandomPerson(luckyDraw){
  3. var index = Math.floor(Math.random() * (luckyDraw.length));
  4. return luckyDraw[index];
  5. }
  6. pickRandomPerson(luckyDraw); // John
  7. // Lodash
  8. _.sample(luckyDraw); // Colin

10. Error handling for JSON.parse

  1. // Using try-catch to handle the JSON.parse error
  2. function parse(str){
  3. try {
  4. return JSON.parse(str);
  5. }
  6. catch(e) {
  7. return false;
  8. }
  9. }
  10. // With Lodash
  11. function parseLodash(str){
  12. return _.attempt(JSON.parse.bind(null, str));
  13. }
  14. parse('a'); // false
  15. parseLodash('a'); // Return an error object
  16. parse('{"name": "colin"}'); // Return {"name": "colin"}
  17. parseLodash('{"name": "colin"}'); // Return {"name": "colin"}
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注