// 柯里化定义:一个函数可以接受多个参数,反复被调用
// fn(1,2,3,4,5)(6,7)(8,9,10) 该技术被命名为函数柯里化
// 例子:求和功能,得到 55 的结果
// 不固定参数个数的函数 √
// 第一次执行返回函数 √
// 后续执行仍然返回函数 √
// 能缓存参数 √
// 内部函数 闭包 二次缓存函数 √
// 闭包的应用场景:避免全局变量的命名冲突
function currying() {
// arguments:获取参数;伪数组:其具备数组的属性,不包含函数
const args = Array.prototype.slice.call(arguments)
// const args = [].__proto__.slice.call(arguments) // 也可以使用 [].__proto__ 对象原型通过原型链查找 slice 方法
// Array.prototype.slice 是一原型上的方法
// call 改变函数调用内部 this 指向(call:多个参数;apply:数组;bind:多个参数,返回新函数)
// 数组方法依赖于内部是 this 数据容器来执行
// console.log(args); // 真实数组
// 一个函数访问外部的自由变量 就形成闭包 (ps:函数嵌套函数是高阶函数,不是闭包)
const inner = function () {
// console.log(args);
args.push(...arguments)
return inner
}
// 如何获取结果值?
// 1.单独写方法获取结果值(只能获取值)
inner.getValue = function () {
return args.reduce((res, ele) => {
return res + ele
}, 0)
}
// 额外需求:可以允许将返回值,进行二次计算
// 2.早期浏览器可以使用 toString 直接返回值;不规范,现在被禁止了
// inner.toString = inner.getValue = function(){
// return args.reduce((res,ele)=>{
// return res + ele
// }, 0)
// }
// 3.修改 inner 计算原始数据类型的方式
// 在 Symbol.toPrimitive 属性 (用作函数值) 的帮助下,一个对象可被转换为原始值。
// 该函数被调用时,会被传递一个字符串参数 hint ,表示要转换到的原始值的预期类型。
// hint 参数的取值是 "number"、"string" 和 "default" 中的任意一个。
inner.__proto__[Symbol.toPrimitive] = function(hint){
if(hint == 'number'){
return inner.getValue() // 预期为计算时直接返回值
}
if(hint == 'string'){
return inner.toString()
}
return true
}
return inner
}
const res = currying(1, 2, 3, 4, 5)(6, 7)(8, 9, 10)
// 方法获取
// const resNum = res.getValue() // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// console.log(resNum) // 55
// 可以允许将返回值,进行二次计算
console.log(res - 1 ) // 54