Lodash-fp模块、Lodash-map方法的小问题、Pointfree

Lodash中的FP模块

  • 我们在使用函数组合解决问题的时候,会使用到lodash中提供的一些方法,但如果这些方法有多个参数的时候,我们需要对这些方法进行柯里化的处理,我们需要重新去包装这些方法,稍微有些麻烦,接下来我们来介绍lodash中的fp模块
  • lodash/fp
    • lodash 的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变 auto-curried、iteratee-first、data-last
// lodash 模块   --- 数据在前,方法在后
const _ = require('lodash')

console.log(_.map(['a', 'b', 'c'], _.toUpper))
// => [ 'A', 'B', 'C' ]

console.log(_.map(['a', 'b', 'c']))
// => [ 'a', 'b', 'c' ]

console.log(_.split('Hello World', ' '))
// => [ 'Hello', 'World' ]


// lodash/fp 模块 --- 方法在前,数据在后
const fp = require('lodash/fp')

console.log(fp.map(fp.toUpper, ['a', 'b', 'c']))
console.log(fp.map(fp.toUpper)(['a', 'b', 'c']))
// => [ 'A', 'B', 'C' ]

console.log(fp.split(' ', 'Hello World'))
console.log(fp.split(' ')('Hello World'))
// => [ 'Hello', 'World' ]
  • lodash 与 lodash/fp 在实际使用时的区别
// lodash将 NEVER SAY DIE 转化为 never-say-die
const _ = require('lodash')

const map = _.curry((fn, array) => _.map(array, fn))
const split = _.curry((sep,str) => _.split(str,sep))
const join = _.curry((sep, array) => _.join(array, sep))

const f = _.flowRight(join('-'), map(_.toLower), split(' '))
console.log(f('NEVER SAY DIE'))


// 使用lodash/fp模块
const fp = require('lodash/fp')

const f = fp.flowRight(fp.join('-'), fp.map(fp.toLower), fp.split(' '))
console.log(f('NEVER SAY DIE'))

lodash 和 lodash/fp 模块中 map 方法的区别

// 把一个字符串数组中的所有元素都转换为整形

// lodash

/**
 * 数据优先,函数之后
 * 
 * 输出结果为 --- [23, NAN, 2] --- 我们来分析一下
 * 
 * 我们先来看一下调用Map方法时传递的parseInt这个函数,有哪些参数
 * 
 * 当我们调用Map这个函数的时候,此时他需要接受三个参数,
 * 分别是:value - index|key - collection
 *          如果是数组,第二个位置会传递index索引
 *          对象的话就会传递一个key
 * 最后就是一个集合collection
 * 
 * 我们现在展开这个执行过程:
 *      当我们调用map是,他回去遍历我们数组中的每一个元素,并且把没一个元素都传递给parseInt进行处理
 * 
 * 第一次调用时:   parseInt('23', 0, array)
 * 第二次调用时:   parseInt('8', 1, array)
 * 第三次调用时:   parseInt('10', 2, array)
 * 
 * 但是parseInt的第二个参数的意思其实是将这个字符串转换为几进制,通过查询文档得知,他的取值范围是2-36
 * 
 * 我们传递0的时候他也可以执行,这个时候转换的是10进制数据,
 * 传递1就不行了,是不支持的,所以是NAN
 * 传递2的时候直接转换为2进制,10在2进制中就是2
 * 
 * 但是这个值不是我们预期的值,我们预期的值是[23, 8, 10]
 * 
 * 这个时候我们可以自己封装一个parseInt,让他只接收一个参数,或者使用lodash/fp来处理
 * */ 
const _ = require('lodash')
console.log(_.map(['23', '8', '10'], parseInt))
// => [23, NAN, 2]


/**
 * 我们使用lodash/fp调用map的时候,我们再来观察一下他接受的参数
 * 
 * Map只传递一个参数的时候,我们接受的是一个函数,因为fp模块中这些函数的方法时函数优先的
 * 我们当前这个函数之接受一个参数,这是跟刚才不一样的地方,刚刚lodash的map中所接受的是三个参数
 * 这就是其中的差别,也是lodash/fp没问题的原因!
 * */ 
const fp = require('lodash/fp')
console.log(fp.map(parseInt, ['23', '8', '10']))
// => [23, 8, 10]

Point Free

  • 是一种编程的风格,具体实现是函数组合,它更抽象一些,
  • Point Free:我们可以把数据处理过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数
    • 不需要指明处理的数据
    • 只需要合成运算过程
    • 需要定义一些辅助的基本运算函数(我们之前使用函数组合解决问题的时候其实就是 Point Free 模式)
    const f = fp.flowRight(fp.join('-'), fp.map(fp.toLower), fp.split(' '))
    
  • 案例演示
// Hello World ---> hello_world

/**
 * 非Point Free
 * 
 * 先定义一个函数来接受一个我们要处理的数据,接下来在这个函数中对这个数据进行处理,得到我们想要的结果
 * */ 
function f (world) {
     
    return world.toLowerCase().replace(/\s+/g, '_')
}

/**
 * Point Free
 * 
 * 先定义一些基本的运算函数,然后将其合成为一个新的函数,在合成的过程中,我们不需要指明我们需要处理的数据
 * 
 * 函数式编程的核心:把运算过程抽象为函数
 * 
 * 而Point Free 模式就是把我们抽象出来的函数,在合成为一个新的函数,这个合成的过程其实又是一个抽象的过程
 * 在这个抽象的过程我们依然不需要关注数据
 * */ 
const fp = require('lodash/fp')

// fp中的方法都是被柯里化过得,所以我们可以传递部分参数,让其返还一个函数
// 第一个:正则表达式 --- 替换的条件
// 第二个:替换为什么元素
// 第三个:处理的数据
const f = fp.flowRight(fp.replace(/\s+/g, '_'), fp.toLower)

fp.replace
console.log(f('Hello World'))

Point Free 案例

// world wild web ==> W. W. W

const fp = require('lodash/fp')

// 普通版
// const f = fp.flowRight(fp.join('. '), fp.map(fp.first), fp.map(fp.toUpper), fp.split(' '))

// 优化版
const f = fp.flowRight(fp.join('. '), fp.map(fp.flowRight(fp.first, fp.toUpper)), fp.split(' '))

console.log(f('world wild web'))

你可能感兴趣的:(javascript)