高阶函数(Higher-order function)
// 定义一个类似于js中数组方法forEach的函数
// 接收两个参数 一个是数组 另一个是数组中成员要执行的函数
function myForEach (array, fn) {
for(var i=0; i<array.length; i++ ){
fn(array[i])
}
}
// test
myForEach(['tom','jerry','jim'],item =>{ console.log(item) })
// 一个函数返回另一个函数
function makeFn () {
let msg = 'Hello function'
return function () {
console.log(msg)
}
}
// test
// 第一种调用方式
const fn = makeFn()
fn() //Hello function
// 第二种调用方式
makeFn()()///Hello function
// 闭包典型案例
for(var i=0; i<10; i++){
((j)=>{
setTimeout( ()=>{
console.log(j)
} )
})(i)
}
纯函数其实就是数学中的函数概念 类似于 y=f(x),用来描述输入和输出的对应关系,是函数式编程重要的概念。
相同的输入永远会得到相同的输出,而且没有任何可观察的副作用。
let numbers = [1, 2, 3, 4, 5]
// 纯函数
// 对于相同的函数,输出是一样的
// slice方法,截取的时候返回截取的函数,不影响原数组
numbers.slice(0, 3) // => [1, 2, 3]
numbers.slice(0, 3) // => [1, 2, 3]
numbers.slice(0, 3) // => [1, 2, 3]
// 不纯的函数
// 对于相同的输入,输出是不一样的
// splice方法,返回原数组,改变原数组
numbers.splice(0, 3) // => [1, 2, 3]
numbers.splice(0, 3) // => [4, 5]
numbers.splice(0, 3) // => []
因为对于相同的输入始终有相同的结果,那么可以把纯函数的结果缓存起来,可以提高性能
function memoize(f){
// 定义一个对象用于记录纯函数的参数和执行结果
let cache = {}
return function(){
// 将传入的参数作为对象的key
let key = JSON.stringfiy( arguments )
// 如果key有对应值说明是再次调用直接获取缓存中的值
cache[key] = cache[key] || f.apply(f,arguments)
return cache[key]
}
}
function getArea(r) {
console.log(r)
return Math.PI * r * r
}
let getAreaWithMemory = memoize(getArea)
console.log(getAreaWithMemory1(4))
console.log(getAreaWithMemory1(4))
console.log(getAreaWithMemory1(4))
// 4
// 50.268245743669
// 50.268245743669
// 50.268245743669
纯函数让测试更加的方便
副作用就是让一个函数变得不纯,纯函数是相同的输入返回相同的输出,如果函数依赖于外部的状态就无法保证输出相同
比如纯函数中如果依赖于 全局变量进行计算 那么只要改变了全局变量 就会导致函数不纯
当函数有多个参数的时候,我们可以对函数进行改造。我们可以调用一个函数,只传递部分的参数(这部分参数以后永远不变),然后让这个函数返回一个新的函数。新的函数传递剩余的参数,并且返回相应的结果
函数的柯里化可以帮助我们解决函数中的硬编码问题
// 定义一个checkAge函数
// 先传递比较年龄的min
function checkAge (min) {
return function (age) {
return age >= min
}
}
// 使用es6改写
let checkAge = min => (age => age >= min)
_.curry(func)
const _ = require('lodash')
//match函数是根据一些正则,匹配字符串,返回匹配结果
const match = _.curry((reg, str) => str.match(reg))
//haveSpace函数是一个匹配空格的函数
const haveSpace = match(/\s+/g)
//haveNumber函数是一个匹配数字的函数
const haveNumber = match(/\d+/g)
//filter函数是定义一个数组和过滤规则,返回符合匹配规则的数组
const filter = _.curry((func, array) => array.filter(func))
//findSpace函数是匹配数组元素中有空格并返回符合情况的数组的函数
const findSpace = filter(haveSpace)
柯里化的好处就是我们可以最大程度的重用我们的函数
function getSum(a, b, c) {
return a + b + c
}
function curry(func) {
return function curried(...args) {
// 函数的length属性获得函数形参个数
// es6的...args 函数的参数扩展 获取传入的不固定数量的实参
if (args.length < func.length) {
return function () {
// 第一部分参数在args里面,第二部分参数在arguments里面,要将两个合并并且展开传递
// concat函数要合并两个数组,arguments为伪数组,所以用Array.from进行转换
return curried(...args.concat(Array.from(arguments)))
}
}
// 如果实参个数大于等于形参个数 返回func的调用结果
return func(...args)
}
}
let s1=curry(getSum)
console.log(s1(1)(2)(3));
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- nryq.cn 版权所有 赣ICP备2024042798号-6
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务