《JavaScript函数式编程》1~3 读后感

  《JavaScript函数式编程》一书从语言,业务场景,程序设计的角度阐述了为什么JS需要函数式编程,JS函数式编程实际使用的场景及优势。

  本书的1-3章,介绍了什么是函数式编程,JS语言中函数式编程的特性,以及如何使用函数式编程解决实际场景。

  函数式编程是一种代码组织形式,它相对于命令式的编程概念。函数式编程思想简单来说,就是一个纯度的,最小功能化的,通过流方式组织上下文的编程模式。

  纯度指的为一个函数的参数和返回值之间的映射关系,通俗来说,相同的参数输入将会得到相同结果的输出,函数内部与外部没有赋值上的交互。简单看一个场景,全局拥有一个变量count为0,实现函数increment,每次调用得到count + 1的结果,然后把increment函数调用两次。通常使用命令式我们将会这么写:

var count = 0;
function increment() {
    count++;
}
increment();
increment();

  这种命令式的写法能够很快直观的完成所需要的功能,但是它有两个问题:

  1. 如果想要知道count的值,你必须记住increment每次的调用。
  2. 直接操作函数外部的变量,当出现多个increment之外的函数操作一个变量时,调用顺序稍有问题,结果将达不到预期。

  现在用函数式编程来改写这段简易逻辑:

var count = 0;
function increment(count) {
    return count + 1;
}
count = new Array(2)
  .fill(undefined)
  .reduce((accumulator) => increment(accumulator), count);

  首先increment函数不再与外部的任何变量存在交互了。它变为了一个非常具有纯度的函数,它的输出是可预期的,永远是入参count + 1。其次count赋值的过程被整合到了一起,以一个清晰的流式的概念呈现出来,在操作多的时候,非常的直观,而不用像命令式去数执行了几次increment

  函数式编程鼓励功能的拆分,实现最小的功能化。然后以一种的方式把功能组合起来。比如我们现在存在一组名字['alonzo church', 'Haskell curry', 'stephen_kleene', 'John Von Neumann', 'stephen_kleene']。我们需要把这组名字格式规范化:1.名字开头都是大写;2.名字中间使用空格分开,然后去掉其中重复的名字。使用命令式的方式应该是这样的:

const names = ['alonzo church', 'Haskell curry', 'stephen_kleene', 'John Von Neumann', 'stephen_kleene'];
const result = [];
for (let i = 0; i < names.length; i++) {
    var n = name[i];
    // n == null即可判空null和undefined
    if (n !== undefined && n !== null) {
        var ns = n.replace(/_/, ' ').split(' ');
        for (let j = 0; j < ns.length; j++) {
            var p = ns[j];
            p = p.charAt(0).toUpperCase() + p.slice(1);
            ns[j] = p;
        }
        // 去重
        if (result.indexOf(ns.join(' ')) < 0) {
            result.push(ns.join(' '));
        }
    }
}

  上面这段逻辑中,首先对数组进行判空操作,然后把所有带_下标的的名字替换成空格,然后利用字符串转数组循环将每一项第一个英文字母变为大写,然后执行去重。在函数式的概念中,这些逻辑应该拆分为一个个的单元块,然后组织起来。

// notVoid -> 非空值, uniq -> 过滤数组重复, startCase -> 首字母大写,具体逻辑未实现
const result = name
    .filter(notVoid)
    .map(s => s.replace(/_/, ' '))
    .uniq()
    .map(startCase)

  我们可以看到,name作为一个出发点,数组像流水一样经过filter -> map -> uniq -> map,最后得出我们想要的结果。且不论代码量的实现,即使在没有注释的情况下,我们也能根据函数的语义清晰的阅读出name是经过哪些数据处理得到result这个结果的。

  最小功能化模块设计结构也能为后续的维护或者功能迭代带来极大的方便。比如我现在更改功能需求,需要筛选出首字母在a-k之间的名称。第一种命令式的组织方式,就需要在if结构中进行维护。第二种维护方式只需要在filter这一步把notVoid替换为新的功能实现函数即可。

  JavaScript虽然有着类C的语法,但是在语法层面上更多借鉴了scheme。JS拥有闭包原型链等一系列函数式编程需要的语言特性。在JS中,函数作为一等公民,可以作为参数传递给另一个函数。这为函数式编程的柯里化以及高阶函数的概念实现提供了完美的语言环境。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值