函数式编程
柯里化(Currying)
柯里化是函数式编程的基础 主要的想法在于利用函数式编程的概念
利用闭包的特性把原本是接受多个参数的函数封装成只接受一个参数的函数(单函数参数)
后面再配合组合的方式使用 compose 函数
1 | function curry(fn) { |
组合函数(Compose-lodash)
把一组函数组合成数据管道 按照从右到左的次序依次执行
所有被组合的函数都必须是单函数参数(多数是柯里化以后的函数)
1 | function compose(...args) { |
Point-Free
在函数组合的基础上继续提升 从 data-first 变成 method-first
用这样的方法来构造函数组合 构造时并不涉及数据 而执行时再把需要用到的数据传进去
按照一定的步骤把小的函数给组合起来 实现特定的目的
这里可以用 loadsh 里面的 fp 模块实现
1 | const firstLetterToUpper = fp.flowRight( |
函子(Functor)
基本概念
首先要明确一下这个概念的由来
在传统的函数式编程中 所有的函数均应该为纯函数 也就是说这些函数本身都是没有副作用的函数
副作用:函数执行时不引起其他变量的变化,函数没有中间中间状态
然而在实际应用中 除了功能单一的一些工具类的函数 大部分的函数都是为了业务构造的
他们是不可能做到完全避免副作用的 所以函子的概念就诞生了
函子把要被改变的变量和要改变这个变量的方法封装到听一个 class 中
在使用的时候从外部传入一个函数来执行想做的操作 同时这个操作也会返回一个新的函子
这样可以做到链式操作 函子之中包裹的这个值是永远不会被直接取出来操作的
1 | //简单的函子的演示 |
Maybe 函子
函子可以按照其功能或用法的特点归类成不同的函子
比如基本的函子里面是没有判断传入的 value 值是不是为空或者 null 的
所以可以在容器中加入判断 在 value 为空时不做任何处理 这样直接返回新函子
1 | // MayBe 函子 |
其他函子与常用库
Either 函子, IO 函子, Task 函子等等其他函子
具体写可以使用FolkTale
函数式编程的面试题
1 | const arrat = ["23", "8", "10"]; |
这里的错误是因为 map 函数本身的定义是这样的
1 | var new_array = arr.map(function callback(currentValue[, index[, array]]) { |
详细解释
callback
生成新数组元素的函数,使用三个参数:
currentValuecallback数组中正在处理的当前元素index可选callback数组中正在处理的当前元素的索引array可选map方法调用的数组。
而 parseInt 的定义是这样的
parseInt(string, radix);
string要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用
ToString抽象操作)。字符串开头的空白符将会被忽略radix可选从
2到36,表示字符串的基数。例如指定 16 表示被解析值是十六进制数。请注意,10 不是默认值
也就是说当我们在调用 parseInt 的时候我们是没有指定 radix 的
而当 radix 取值为 0, undefined 或者 null 时 parseInt 不会以 10 进制来解析
所以实际上当执行上一步操作时 真正得到的结果是这样的
1 | parseInt("23", 0); // parseInt没有第三个参数,所以map传递进来第三个参数array可以被忽略 |
这个题可以用 lodash 中的 map 方法来做
注意 这里如果只用 lodash 中的普通的 map 方法也是会出问题的
1 | const _ = require("lodash"); |