博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一些小技巧让JS代码更优雅
阅读量:6260 次
发布时间:2019-06-22

本文共 3209 字,大约阅读时间需要 10 分钟。

今天翻了翻一年多前写的代码,感觉当年年轻的自己写下的代码真是图样啊(然而现在也没好到哪里去 /w\)。近期看了好多函数式编程以及设计模式的书和文章,于是想分享一些让JS代码更优雅的小技巧。


一、善用函数式编程

假设我们有这样的需求,需要先把数组foo中的对象结构更改,然后从中挑选出一些符合条件的对象,并且把这些对象放进新数组result里。

var foo = [{    name: 'Stark',    age: 21},{    name: 'Jarvis',    age: 20},{    name: 'Pepper',    age: 16}]//我们希望得到结构稍微不同,age大于16的对象:var result = [{    person: {        name: 'Stark',        age: 21    },    friends: []},{    person: {        name: 'Jarvis',        age: 20    },    friends: []}]

从直觉上我们很容易写出这样的代码:

var result = [];//有时甚至是普通的for循环foo.forEach(function(person){    if(person.age > 16){        var newItem = {            person: person,            friends: [];        };        result.push(newItem);    }})

然而用函数式的写法,代码可以优雅得多:

var result = foo    .filter(person => person.age > 16)    .map(person => ({        person: person,        friends: []    }))

还有比如在各种文章里说烂了的数组求和:

var foo = [1, 2, 3, 4, 5];//不优雅function sum(arr){    var x = 0;    for(var i = 0; i < arr.length; i++){        x += arr[i];    }    return x;}sum(foo) //15//优雅foo.reduce((a, b) => a + b) //15

这些只是很简单的例子,更多关于函数式编程的知识,可以参考这里:


二、lodash里一些很好用的东西

lodash是一个著名的JS工具库,里面存在众多函数式的方法和接口,在项目中引入可以简化很多冗余的逻辑。

1、_.flow解决函数嵌套过深

//很难看的嵌套a(b(c(d(...args))));//可以这样改善_.flowRight(a,b,c,d)(...args)//或者_.flow(d,c,b,a)(...args)

2、_.memoize加速数学计算

在写一些Canvas游戏或者其他WebGL应用的时候,经常有大量的数学运算,例如:

Math.sin(1)

Math.sin()的性能比较差,如果我们对精度要求不是太高,我们可以使用_.memoize做一层缓存

var Sin = _.memoize(function(x){    return Math.sin(x);})Sin(1) //第一次使用速度比较慢Sin(1) //第二次使用有了cache,速度极快

注意此处传入的x最好是整数或者较短的小数,否则memoize会极其占用内存。

事实上,不仅是数学运算,任何函数式的方法都有可缓存性,这是函数式编程的一个明显的优点

3、_.flatten解构嵌套数组

_.flatten([1, 2], [3, 4]); // => [1, 2, 3, 4]

这个方法和Promise.all结合十分有用处。

假设我们爬虫程序有个getFansList方法,它可以根据传入的值x,异步从粉丝列表中获取第 x*20 到 (x+1)*20 个粉丝,现在我们希望获得前1000个粉丝:

var works = [];for (var i = 0; i < 50; i++) {    works.push(getFansList(i))}Promise.all(works)    .then(ArrayOfFansList=> _.flatten(ArrayOfFansList))    .then(result => console.log(result))

前段时间写的中就能看到类似的写法

4、_.once配合单例模式

有些函数会产生一个弹出框/遮罩层,或者负责app的初始化,因此这个函数是执行且只执行一次的。这就是所谓的单例模式,_.once大大简化了我们的工作量

var initialize = _.once(createApplication);initialize();initialize();// 这里实际上只执行了一次 initialize// 不使用 once 的话需要自己手写一个闭包

三、Generator + Promise改善异步流程

有时我们遇到这样的情况:

getSomethingAsync()    .then( a => method1(a) )    .then( b => method2(b) )    .then( c => method3(a,b,c) ) //a和b在这里是undefined!!!

只用 Promise 的话,解决方法只有把 a、b 一层层 return 下去,或者声明外部变量,把a、b放到 Promise 链的外部。但无论如何,代码都会变得很难看。

用 Generator 可以大大改善这种情况(这里使用了Generator的执行器co):

import co from 'co';function* foo(){    var a = yield getSomethingAsync();    var b = yield method1(a);    var c = yield method2(b);    var result = yield method3(a,b,c);    console.log(result);}co(foo());

当然,Generate 的用处远不止如此,在异步递归中它能发挥更大的用处。比如我们现在需要搜索一颗二叉树中value为100的节点,而这颗二叉树的取值方法是异步的(比如它在某个数据库中)

import co from 'co';function* searchBinaryTree(node, value){    var nowValue = yield node.value();    if(nowValue == value){        return node;    }else if(nowValue < value){        var rightNode = yield node.getRightNode()        return searchBinaryTree(rightNode, value);    }else if(nowValue > value){        var leftNode = yield node.getLeftNode()        return searchBinaryTree(leftNode, value);    }}co(searchBinaryTree(rootNode, 100))

转载地址:http://gvhsa.baihongyu.com/

你可能感兴趣的文章
【转载】APK反破解之四:Android代码动态加载技术
查看>>
(转)iOS Wow体验 - 第三章 - 用户体验的差异化策略
查看>>
vsftp配置大全---超完整版
查看>>
继:我朝特有需求之--英文字符占 0.5 个,中文字符占 1 个
查看>>
关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error
查看>>
ASP.NET Word/Excel 权限问题
查看>>
IOS 3D UI --- CALayer的transform扩展
查看>>
img绝对定位在div中间,img上下稍微移动问题
查看>>
前序遍历构造已知二叉树(二叉链表实现)(Java)
查看>>
查看CentOS版本
查看>>
关于VS 中 HttpHandler 的设置 500.23
查看>>
19.04.27--作业 打字游戏
查看>>
连接Access数据库的DAL层操作代码
查看>>
mysql重置auto_increment字段
查看>>
MySQL的优化
查看>>
bzoj1702[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列*
查看>>
分享到
查看>>
OpenCV Error: Assertion failed (data0.dims <= 2 && type == 5 && K > 0) in cv::kmeans
查看>>
【开篇】洛神赋
查看>>
Vue.js 学习报告
查看>>