JavaScript工具函数-用Lodash减少LOC,并改善你的应用程序逻辑清晰

开发JavaScript应用程序的时候,我们经常需要自己编写实用方法等作为我们的实用(工具函数)模块。那么,什么是实用模块?

实用类就是定义一组经常执行的方法,重复使用功能的类。 – 维基百科

从处理字符串和对象到集合迭代器,总是会需要实用功能来完成工作的情况。

即使是采用主流的ES6,我敢说,JavaScript开发人员仍然无法获得像Objective-C或Ruby那样多的语法糖。 因此,在JavaScript应用中,仍然普遍需要我们编写大量重复的自定义工具函数。

然而,最近我很喜欢一个JavaScript库,它提供很多干净,高性能的实用方法 – Lodash

YHvwPgwojjsFa

如果jQuery是DOM操作的瑞士军刀,那么Lodash对于Javascript来说相当于是蝙蝠侠的实用腰带。蝙蝠侠总是用他信赖的腰带上的小工具摆脱棘手的情况。

以下是我在JavaScript应用已经停止重写的10个实用方法,当然对于不同的工作,你很可能也会需要其他的工具函数, 本文仅作为一个入门Lodash的引子。

==================此处强势插入广告==================

Lodash 中文文档 http://www.css88.com/doc/lodash/ (当前最新 v4.16.1 版本)

================================================

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

for循环是一个常见的使用场景,但是它会污染附加变量作用域(scope)。 组合使用数组和apply方法,我们可以实现N个循环,而无需创建一个额外的变量。 但是,这种写法不够直观。Lodash总的_.times方法就非常的直观易用。

注意:如果您的循环不是很繁琐,建议你使用基本的for循环或while反向循环,这样迭代的性能更高。

2)迭代数组并返回每一项中深度嵌套的属性
js 代码:
  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.  
  10. // Array's map method.
  11. ownerArr.map(function(owner){
  12. return owner.pets[0].name;
  13. });
  14.  
  15. // Lodash
  16. _.map(ownerArr, 'pets[0].name');

Lodash中的map方法和JavaScript中原生的数组方法非常的像,但它还是有非常有用的升级。 你可以通过一个字符串而不是回调函数来浏览深度嵌套的对象属性。

注意:之前版本中的_.pluck方法在Lodash v4中已经被删除,可用使用_.map方法替换。

js 代码:
  1. _.pluck(ownerArr, 'pets[0].name');
  2. _.map(ownerArr, 'pets[0].name');

上面两个方法是等价的,在使用方面,没有区别。

3)创建一个大小为N的数组,并且为他们添加相同的前缀
js 代码:
  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.  
  4. // Array's map method.
  5. Array.apply(null, Array(6)).map(function(item, index){
  6. return "ball_" + index;
  7. });
  8.  
  9.  
  10. // Lodash
  11. _.times(6, _.uniqueId.bind(null, 'ball_'));

从前面的例子中我们已经知道了_.times的作用。如果你将它和_.uniqueId方法组合使用, 我们可以获得一个更简洁的解决方案。如果你不想重复的声明上下文,Lodash也提供了一个可选方案。

避免使用.bind(null,…)
js 代码:
  1. // Lodash
  2. _.times(6, _.partial(_.uniqueId, 'ball_'));

_.partial方法和原生的bind方法基本上完成了相同的工作,除了它假设当前的上下文为this。 因此,没必要再额外的指定上下文参数。

4)深度克隆JavaScript对象
js 代码:
  1. var objA = {
  2. "name": "colin"
  3. }
  4.  
  5. // Normal method? Too long. See Stackoverflow for solution: http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
  6.  
  7. // Lodash
  8. var objB = _.cloneDeep(objA);
  9. objB === objA // false

深度克隆JavaScript对象是困难的,并且也没有什么简单的解决方案。你可以使用奇特的原生解决方案: JSON.parse(JSON.stringify(objectToClone))进行深度克隆。但是,这种方案仅在对象内部没有方法的时候才可行。

Lodash提供了_.cloneDeep方法来帮你简单的完成对象的深度克隆操作。当然,使用_.clone你还能灵活的指定克隆的深度。

5)在指定范围内获取一个随机值
js 代码:
  1. // Get a random number between 15 and 20.
  2.  
  3. // Naive utility method
  4. function getRandomNumber(min, max){
  5. return Math.floor(Math.random() * (max - min + 1)) + min;
  6. }
  7.  
  8. getRandomNumber(15, 20);
  9.  
  10. // Lodash
  11. _.random(15, 20);

_.random方法要比上面的原生方法更强大与灵活。要想返回随机浮点型的数字,和只传入一个参数作为最大值,我们自定义的实用方法中将添加大量的代码。

_.random的附加选项

js 代码:
  1. _.random(20); // 返回 0 到 20的随机数
  2. _.random(15, 20, true); // 返回 15 到 20的浮点型随机数
6)扩展对象
js 代码:
  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.  
  10. var objA = {"name": "colin", "car": "suzuki"};
  11. var objB = {"name": "james", "age": 17};
  12.  
  13. objA.extend(objB);
  14. objA; // {"name": "james", "age": 17, "car": "suzuki"};
  15.  
  16. // Lodash
  17. _.assign(objA, objB);

_.assign方法也可以接收多个参数对象进行扩展。

扩展多个对象
js 代码:
  1. var objA = {"name": "colin", "car": "suzuki"};
  2. var objB = {"name": "james", "age": 17};
  3. var objC = {"pet": "dog"};
  4.  
  5. // Lodash
  6. _.assign(objA, objB, objC)
  7. // {"name": "james", "car": "suzuki", "age": 17, "pet": "dog"}
7)从对象中删除属性
js 代码:
  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.  
  9. var objA = {"name": "colin", "car": "suzuki", "age": 17};
  10.  
  11. objA.remove(['car', 'age']);
  12. objA; // {"name": "colin"}
  13.  
  14. // Lodash
  15. objA = _.omit(objA, ['car', 'age']); // {"name": "colin"}

原生的方法只能传递数组作为参数。有时我们可能需要对字符串参数进行单个key的删除,甚至是传入一个比较函数。

更多使用案例
js 代码:
  1. var objA = {"name": "colin", "car": "suzuki", "age": 17};
  2.  
  3. // Lodash
  4. objA = _.omit(objA, 'car'); // {"name": "colin", "age": 17};
  5. objA = _.omit(objA, _.isNumber); // {"name": "colin"};

如果想要达到这样的结果,使用原生的实用函数需要增加大量的代码,_.omit方法帮助我们轻松处理所有这钟情况。

还应注意的是,_.omit会返回一个新对象,而不会直接引用传递的对象(不会修改传递的对象)。如果你想要改变前的对象不受到删除属性的影响,这是非常有用的。

8)从某个对象中选择部分属性组成新的对象
js 代码:
  1. // Naive method: Returning a new object with selected properties
  2. Object.prototype.pick = function(arr) {
  3. var _this = this;
  4. var obj = {};
  5. arr.forEach(function(key){
  6. obj[key] = _this[key];
  7. });
  8.  
  9. return obj;
  10. };
  11.  
  12. var objA = {"name": "colin", "car": "suzuki", "age": 17};
  13.  
  14. var objB = objA.pick(['car', 'age']);
  15. // {"car": "suzuki", "age": 17}
  16.  
  17. // Lodash
  18. var objB = _.pick(objA, ['car', 'age']);
  19. // {"car": "suzuki", "age": 17}
  20.  

_.pick方法与_.omit方法正好相反,它会从一个对象中选择指定的属性组装成新的对象。 和_.omit一样,_.pick也会返回新的对象,并且能够传入字符串、数组、比较器函数。

9)从列表中随机的选择列表项
js 代码:
  1. var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];
  2.  
  3. function pickRandomPerson(luckyDraw){
  4. var index = Math.floor(Math.random() * (luckyDraw.length));
  5. return luckyDraw[index];
  6. }
  7.  
  8. pickRandomPerson(luckyDraw); // John
  9.  
  10. // Lodash
  11. _.sample(luckyDraw); // Colin

_.sample方法还配备了一个额外的优秀特点 – 从列表中选择多个随机的元素返回。

多个随机项
js 代码:
  1. var luckyDraw = ["Colin", "John", "James", "Lily", "Mary"];
  2.  
  3. // Lodash - Getting 2 random item
  4. _.sample(luckyDraw, 2); // ['John','Lily']
10)JSON.parse的错误处理
js 代码:
  1. // Using try-catch to handle the JSON.parse error
  2. function parse(str){
  3. try {
  4. return JSON.parse(str);
  5. }
  6.  
  7. catch(e) {
  8. return false;
  9. }
  10. }
  11.  
  12. // With Lodash
  13. function parseLodash(str){
  14. return _.attempt(JSON.parse.bind(null, str));
  15. }
  16.  
  17. parse('a'); // false
  18. parseLodash('a'); // Return an error object
  19.  
  20. parse('{"name": "colin"}'); // Return {"name": "colin"}
  21. parseLodash('{"name": "colin"}'); // Return {"name": "colin"}

如果你在你的应用程序中使用JSON.parse,建议你一定要进行错误处理。未处理的JSON.parse错误就像一个定时炸弹。不要假设你接收到的JSON对象是完全有效的。

虽然我们并不能完全替代 try-catch 实用方法,我们可以设法去掉难看的 try-catch 代码块。_.attempt可以防止JSON.parse抛出一个应用程序错误。相反,它返回一个Error对象。

结论

Lodash已经为我做了很好事情,我会继续在我的JavaScript项目中使用它。它能让我的代码看起来更加的精简, 也提高了我的应用程序逻辑的清晰度。

此外,Lodash也迫使我们以函数式的方式来思考编程。 我们可以将应用切分为若干个小且专注的模块。这种模块化能够提高我们应用程序在测试时的代码覆盖率。

英文原文地址: http://colintoh.com/blog/lodash-10-javascript-utility-functions-stop-rewriting

转载:http://www.css88.com/archives/6275#more-6275

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值