《javascript函数式编程指南》读书笔记三

2019-06-27  本文已影响0人  月半女那

第二部分函数基础部分

模块化且可重用的代码

模块化的意义:将程序分成较小独立的程度。这些部分都是可重复使用的组件,并可以合并为一个系统整体或单独在其他系统中使用

1. 方法链与函数管道

在函数式编程中,函数是输入与输出类型之间的数学映射
函数式编程能够消除方法链中存在的限制,使任何函数的组合都更加灵活。管道是松散结合的有向函数序列。一个函数的输出会作为下一个函数的输入。
方法链通过对象的方法紧密连接,而管道以函数作为组件将函数的输入和输出松散的连接在一起。
函数的输入和输出需要满足的条件


2. 柯里化的函数求值

柯里化是一种在所有参数被提供之前,挂起或延迟函数执行。将多元函数转换成一元函数。柯里化的可替代方案是部分应用和函数绑定

// lodash 中 _.curry()
var sum = function(a, b, c) {
  return a + b + c;
};


var currries = _.curry(sum)
console.log(currries(1)(2)(3)) // 6

2.1. 部分应用和函数绑定
部分应用:通过将函数的不可变参数子集初始化为固定值来创建跟小元数函数的操作
部分应用和柯里化的区别:
主要区别在于参数传递的内部机制和控制

//  _.partial(func, [partials])

var greet = function(greeting, name) {
    return greeting + ' ' + name;
  };
 // 将 greeting这个的值记住,放在闭包中,不会被销毁
  var sayHello = _.partial(greet,'hello')
 const res = sayHello('fff')
 const res1 = sayHello('mmmmm')
 console.log(res,res1) //hello fff hello mmmmm

_.partial创建一个函数来调用func函数并且将局部应用参数添加到新函数接收到是参数列表的最开头。
和_.bind方法类似,但是bind会改变this绑定
 const obj = {
     'user':'fres'
 }

 var greet = function(greeting, punctuation) {
    return greeting + ' ***' + this.user + punctuation;
  };

  const ress =  _.bind(greet,obj,'hi')
  console.log(ress('!')) //hi ***fres!
3. 组合函数管道

一个由纯函数构建的程序本身也是纯的,因此能够进一步组合更为复杂的解决方案,而不会影响系统的其他部分。
本质上看,函数组合是一种将已被分解的简单任务组织成复杂行文的整体过程
3.1. 使用函数组合子来管理程序的控制流
命令式代码中可以使用if-else / for 这样的过程控制机制。但是在函数式中则不能,所以其替代方案--可以使用函数组合子

identify

identify:返回与参数同值的函数
用途:

tap(K-组合子)
_.tap(value,interceptor)
调用一个interceptor并返回value
iterceptor调用1个参数
该方法的目的是进入方法链序列以便修改中间结果
const a = _([1,2,3]).tap(arr => {
    arr.pop();
}).value()

console.log('a',a)  // a [ 1, 2 ]
alt(OR-组合子)

alt组合子能够在提供函数响应的默认行为时执行简单的条件逻辑。该组合子以两个函数为参数,如果第一个函数返回值已定义(不是 false / null / undefined)则返回该值,否则返回第二个结果

const alt = function(f1,f2){
    return function(val){
        return f1(val) || f2(val)
    }
}

或者
_.curry( (f1,f2,val)=> f1(val) || f2(val) )
seq(S-组合子)

seq组合子用于遍历函数序列。它以两个或更多个函数作为参数并返回一个新的函数,会用相同的值顺寻调用所有这些函数

const seq = function(){
    const funcs = Array.prototype.slice.call(arguments);
    return function(val){
        funcs.forEach(element => {
            element(val)
        });
    }
}

function f1(val){
    return val+3
}

function f2(val){
    return val*2
}

const f3 = seq(f1,f2)
f3(4) // 7 8

seq组合子不会返回任何值,只会一个一个的执行一系列操作。

fork(join)组合子

fork组合子用于需要以两种不同的方式处理单个资源的情况,该组合需要以3个函数作为参数,即以一个join函数和两个fork函数来处理提供的输入。两个分叉函数的结果最终传递到的接受两个函数的join函数中

const fork = function(join, func1, func2){
    return function(val){
        return join(func1(val),func2(val))
    }

}

function sum(a, b, c) {
    return a + b + c
}

function len(a, b, c) {
    return arguments.length
}

function device(a, b) {
    return a / b
}

const c = fork(device, sum, len)
console.log(c(1, 2, 3))


基于不可变性和纯性,函数式编程可以有效提程序代码的模块化和可重用性水平
纯函数的组合是函数式编程的支柱

总结
上一篇 下一篇

猜你喜欢

热点阅读