本日翻了翻一年多前写的代码,觉得昔时年青的本身写下的代码真是图样啊(但是如今也没好到哪里去 /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))