第一次更新:10-31
开发方向:BFF(中间层)开发、泛客户端开发、传统Web技术的深入
尽可能的重用函数
概念:将函数作为参数传递给另一个函数
函数作为参数:将函数变得更灵活
函数作为返回值:闭包,柯里化
// 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)
高阶函数的意义:抽象可以帮我们屏蔽细节,只需要关注与我们的目标;高阶函数是用来抽象通用的问题
map
const map = (array, fn) => { let results = [] for (let value of array) { results.push(fn(value)) } return results }
every:检测数组中的元素是否都满足指定条件
const every = (array, fn) => { let result = true for (let value of array) { result = fn(value) if (!result) { break } } return result }
some:检测数组中的元素是否有一个满足指定条件
const some = (array, fn) => { let result = false for (let value of array) { result = fn(value) if (result) { break } } return result }
一个作用域访问另一个作用域变量换一种说法从一个作用域中访问函数内部的函数并且在这一个函数中可以访问到外部函数的成员
作用:延长内部成员作用范围,当外部作用域对内部变量有引用,内存空间就不会被释放
闭包的本质:函数在执行的时候会放到一个执行栈上,当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用而不能被释放,因此内部函数依然可以访问外部函数的成员(函数套函数,这里的内部指的是函数里面函数的作用域)
闭包发生的时候外部函数会从调用栈上移除掉,但是跟闭包相关的变量会被缓存下来
扩展学习:断点 f11
call stack:函数调用栈
anonymous:匿名函数
scope:作用域
global:全局作用域
local:局部作用域
closure:闭包
纯函数:相同的输入始终要得到相同的输出,没有任何可观察的副作用
纯函数与不纯函数对比:
slice:返回数组中指定部分,不会改变原数组 splice:对数组进行操作并返回该数组,会改变原数组
纯函数库:Lodash
纯函数的优势:
memoize方法缓存返回值,是一个纯函数
// 柯里化 function checkAge (min) { return function (age) { return age >= min } } let checkAge18 = checkAge(18) let checkAge20 = checkAge(20) checkAge18(24) checkAge18(20) // ES6 写法 let checkAge = min => (age => age >= min) 说明:ES6写法,首先传入一个参数min,因为要返回另一个函数,所以用小括号扩起,age作为内部函数的参数,通过箭头函数写法返回对应的结果
可以传入一个参数也可以传入多个参数,传入一个参数可以生成一个新的函数
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)
使用柯里化生成具备特定功能的函数
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)
Array.from将伪数组转化为数组
function curry (func) { return function curriedFn (...args) { // 判断实参和形参的个数 if (args.length < func.length) { return function () { return curriedFn(...args.concat(Array.from(arguments))) } } // 实参和形参个数相同,调用 func,返回结果 return func(...args) } }
5、柯里化总结
// 组合函数 function compose (f, g) { return function (x) { return f(g(x)) } } function first (arr) { return arr[0] } function reverse (arr) { return arr.reverse() } // 从右到左运行 let last = compose(first, reverse) console.log(last([1, 2, 3, 4]))
flowRight的使用
const _ = require('lodash') const toUpper = s => s.toUpperCase() const reverse = arr => arr.reverse() const first = arr => arr[0] const f = _.flowRight(toUpper, first, reverse) console.log(f(['one', 'two', 'three']))
组合函数原理模拟
疑问:useState保存的变量和let保存变量的区别
ire(‘lodash’)
const toUpper = s => s.toUpperCase()
const reverse = arr => arr.reverse()
const first = arr => arr[0]
const f = _.flowRight(toUpper, first, reverse)
console.log(f([‘one’, ‘two’, ‘three’]))
组合函数原理模拟 疑问:useState保存的变量和let保存变量的区别