高阶函数

109 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情 函数式编程FP

编程范式分为

1.面向对象

2.面向过程和

3.函数式编程

函数式编程就是用函数表达事物之间关系。 对应数学中的 y = f(x) 用f来表示x和y之间的关系

javascritp中函数是一等公民(First-class Function),因为函数可以当做参数传递,可以当做值返回, 同样也可以用变量存储。

高阶函数

函数作为返回值,或者作为参数


// once
function once (fn) {
  let done = false
  return function () {
    if (!done) {
      done = true
      return fn.apply(this, arguments)
    }
  }
}

let pay = once(function (money) {
  console.log(`支付: ${money} RMB`)
})

pay(5)
pay(5)
pay(5)
pay(5)

常见的高阶函数有forEach map filter every some find findIndex reduce sort等等

好处可以帮我们隐藏掉实现的很多细节,只需要关注目标值x就能得到我们想要的结果y

闭包

子级作用域(内部函数)总是可以访问父级作用域(外部函数)中定义的变量。 父级作用域变量被子级作用域引用导致得不到释放的现象,只有等到子级作用域执行完后才被释放。

本质就是函数在执行栈中执行,执行完后(完成的标致值return})从栈中移除,但是堆中保存的变量,因为被外部引用得不到释放,所以才有内部函数可以访问外部变量。


function makeSalary (base) {
  return function (performance) {
    return base + performance
  }
}

函数柯里化 (Currying)

当判断一个结果多个参数,并且其中一个参数依赖于配置,后台返回等,使得函数相同输入得到不同输出

let mini = 18 
function checkAge (age) {
  return age >= mini
}

checkAge(19)// mini的值不确定,所以得到的结果也不确定。

函数柯里化,即当函数多个参数的时候可以传递一部分参数生成一个新的函数。调用新函数传递剩余的参数

function checkAge (min) {
  return function (age) {
    return age >= min
} }

// ES6 写法
let checkAge = min => (age => age >= min)

let checkAge18 = checkAge(18) let checkAge20 = checkAge(20)
checkAge18(24)
checkAge18(20)

lodash中的_.curry(func) 生成的形函数参数可以任意顺序传,结果不变

const _ = require('lodash') // 要柯里化的函数
function getSum (a, b, c) {
  return a + b + c
}

// 柯里化后的函数
let curried = _.curry(getSum) 
curried(1, 2, 3)
curried(1)(2)(3)
curried(1, 2)(3)

缓存函数memoize, 缓存上次结果。

function getArea (r) {
  console.log(r)
  return Math.PI * r * r
}

// 模拟 memoize 方法的实现

function memoize (f) {
  let cache = {}
  return function () {
    let key = JSON.stringify(arguments)
    cache[key] = cache[key] || f.apply(f, arguments)
    return cache[key]
  }
}

let getAreaWithMemory = memoize(getArea)
console.log(getAreaWithMemory(4))
console.log(getAreaWithMemory(4))
console.log(getAreaWithMemory(4))

函数组合compose

顾名思义就是需要经过多个函数执行后得到结果,我们可以把中间所有执行过程组合成一个新函数,相当于执行组合后的函数就得到了最终结果,默认执行顺序从右向左

y = f(g(h(x)))

即等价于

const fn=compose(f,g,h)
fn(x)



// 组合函数
function compose (f, g) {
  return function (x) {
    return f(g(h(x)))
} }

lodash 中组合函数 flow() 或者 flowRight(),他们都可以组合多个函数 flow() 是从左到右运行flowRight() 是从右到左运行,使用的更多一些