【JS】函数柯里化
固定某些参数,返回接受剩余参数的新函数,如果没有剩余参数,就调用。
将多个参数的函数转换为单个参数的函数
作用:参数复用,延迟计算…
// 传入参数不限,不能丢失传入的参数
function add() {
// 不设置形参 因为传入参数不定
// 用args存放传入参数 arguments是函数参数 但是是对象 但是这里想要args是数组 要进行类型转换
// let args = arguments
// Array.prototype.slice.call将具有length属性的arguments转换为数组
let args = Array.prototype.slice.call(arguments)
let inner = function () {
// inner接收剩余传入的参数,把当前传入的参数 加入到之前的参数数组里
args.push(...arguments)
// let sum = args.reduce((pre, val) => pre + val, 0)
// return sum
// 内部函数返回内部函数 可以处理多个括号
return inner
}
// 函数被隐式转换了
inner.toString = function () {
let sum = args.reduce((pre, val) => pre + val, 0)
return sum
}
return inner
}
// 两种方法拿到结果
console.log(+add(1)(2)(3))//输出函数被隐式转换成字符串
console.log(add(1)(2)(3, 4).toString())
对Array.prototype.slice.call(arguments)的解释
作用:将具有length属性的arguments转换为数组,可以看做是arguments.toArray().slice(),分成两步理解:
(1)其中,arguments是一个具有length属性的对象, 通过call 这个方法,把arguments 指向了Array.prototype.slice方法的作用域,也就是说通过call方法,让Array.prototype.slice对arguments对象进行操作。
(2)Array.prototype.slice就是对该对象使用Array类的slice方法。但是arguments又不是个Array对象。
因为:typeof arguments === “Object” //不是"Array",用arguments.slice()方法,这样是会报错的。
所以这里,我们需要使用Array.prototype.slice, 它的作用就是第一步把arguments转换为一个Array对象,第二步对转换后的Array对象使用slice方法。
参数个数固定时可以这样写:
// 传入5个参数才进行计算
let nums = []
function sum(...args) {
// 把每次当前接受到的数 放入到数组中
nums.push(...args)
// 累加当前的数值 初始值为0
if (nums.length === 5) {
const res = nums.reduce((pre, val) => pre + val, 0)
// 要清空 不然每次往nums后面加
nums = []
return res
} else {
// 内部返回接受剩余参数的新函数
return sum
}
}
console.log(sum(1)(2)(3)(4)(5));//15
console.log(sum(1, 2)(3)(4)(6));//16
// 参数个数可以自定义
function sumMaker(len) {
let nums = []
function sum(...args) {
// 把每次当前接受到的数 放入到数组中
nums.push(...args)
// 累加当前的数值 初始值为0
if (nums.length >= len) {
const res = nums.slice(0, len).reduce((pre, val) => pre + val, 0)
// 要清空 不然每次往nums后面加
nums = []
return res
} else {
// 内部返回接受剩余参数的新函数
return sum
}
}
return sum
}
console.log(sumMaker(5)(1, 2)(3)(4)(5, 6))//15