一些小技能让JS代码更文雅

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

这些只是很简单的例子,更多关于函数式编程的学问,能够参考这里:

JS函数式编程指南 – GitBook

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

lodash是一个有名的JS东西库,内里存在浩瀚函数式的要领和接口,在项目中引入能够简化许多冗余的逻辑。

lodash中文文档

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))
    原文作者:王伟嘉
    原文地址: https://segmentfault.com/a/1190000004868176
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞