【JavaScript】从实现函数柯里化复习 JavaScript 核心知识

// 柯里化定义:一个函数可以接受多个参数,反复被调用
// 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

posted @ 2022-07-03 15:05  努力挣钱的小鑫  阅读(59)  评论(0编辑  收藏  举报