最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 函数 - 函数反柯里化(uncurrying)

    正文概述 掘金(SoulReader)   2021-02-13   549

    参考链接

    函数柯里化

    含义

    柯里化:是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数,核心思想是把多参数传入的函数拆成单(部分)参数函数,内部再返回下一个单(部分)参数函数,依次处理剩余函数

    反柯里化:扩大适用范围,创建一个应用范围更广的函数,使本来只有特定对象才适用的方法,扩展到更多对象

    通用实现

      // 第一种实现方式
      Function.prototype.unCurrying = function() {
        const self = this
        // ...rest 方法相当于使用es6语法的解构赋值使用rest接收入参数组,相当于arguments rest的值是传入的所有参数组成的一个数组
        return function(...rest) {
          return Function.prototype.call.apply(self, rest)
        }
      }
      const push = Array.prototype.push.unCurrying()
      /*
        * 1 为 Function 原型添加 unCurrying 方法,并在执行的时候保存执行 unCurrying 的方法到self
        * 2 借用apply把要借用的函数作为this环境赋予call,并传入之后的形参作为参数执行
      */
    
      // 第二种实现方式
      Function.prototype.unCurrying = function() {
        return this.call.bind(this)
      }
    
      // 第三种实现方式
      function unCurrying(fn) {
        return function(tar, ...argu) {
          return fn.apply(tar, argu)
        }
      }
    

    使用反柯里化

      Function.prototype.unCurrying = function() {
        const self = this
        return function(...rest) {
          console.log(rest, 'uncurrying rest')
          
          return Function.prototype.call.apply(self, rest)
        }
      }
      const push = Array.prototype.push.unCurrying()
      ~function(...rest) {
        console.log(rest, 'before')
        push(rest, 4, 5)
        console.log(rest, 'after')
      }(1,2,3)
    

    反柯里化其实反映的是一种思想 - 扩大方法的适用范围

      Function.prototype.unCurrying = function() {
        const self = this
        return function(...rest) {
          console.log(rest, 'uncurrying rest')
          
          return Function.prototype.call.apply(self, rest)
          // Array.prototype.push.call({a: 3}, 4, 5)
        }
      }
      const push = Array.prototype.push.unCurrying()
      ~function() {
        let rest = {a: 3}
        console.log(rest, 'before')
        push(rest, 4, 5)
        console.log(rest, 'after')
      }(1,2,3)
    

    只要是方法就可以借用 unCurrying 方法

      // call
      var call = Function.prototype.call.unCurrying()
      function $(id) {
        return this.getElementById(id)
      }
      // call()
      call($, document, 'demon')
      /*
        * 解题步骤
        * => Function.prototype.call.apply(Function.prototype.call, [$, document, 'demon'])
        * => Function.prototype.call.call($, document, 'demon')
        * => $.call(document, 'demon')
        * => document.getElementById('demon)
      */
      // unCurrying 借用自己本身
      const unCurrying = Function.prototype.unCurrying.unCurrying()
      const map = unCurrying(Array.prototype.map)
      map({0: 4, 1: 'a', 2: null, length: 3}, n => n + n)
      /*
        * const map = unCurrying(Array.prototype.map) 步骤
        * => Function.prototype.call.apply(Function.prototype.unCurrying, [Array.prototype.map])
        * => Function.prototype.unCurrying.call(Array.prototype.map)
        * => Array.prototype.map.unCurrying()
        * => map = Array.prototype.map.unCurrying()
        * => map({0: 4, 1: 'a', 2: null, length: 3}, n => n + n)
        * => Function.prototype.call.apply(Array.prototype.map, [{0: 4, 1: 'a', 2: null, length: 3}, n => n + n])
        * => Array.prototype.map.call({0: 4, 1: 'a', 2: null, length: 3}, n => n + n)
        * => {0: 4, 1: 'a', 2: null, length: 3}.map(n => n + n)
        * => {0: 8, 1: 'aa', 2: 0, length: 3}
      */
    

    总结

    函数柯里化

      function(arg1, arg2)               // function(arg1)(arg2)
      function(arg1, arg2, arg3)         // function(arg1)(arg2)(arg3)
      function(arg1, arg2, arg3, arg4)   // function(arg1)(arg2)(arg3)(arg4)
    

    反柯里化

      obj.fn(arg1, arg2)             //  fn(obj, arg1, arg2)
    

    终点知识解析

    1. Function.prototype.call.apply(self, rest)

      小例子:

        Math.Max.apply([], [1, 2, 3])
      

      Function.prototype.call.apply(self, rest)过程

      • Function.prototype.call.apply(Array.prototype.push, rest)
      • Array.prototype.push.call(...rest) 所以在传递 rest 的时候,需要操作的对象放在第一位,方便 call 绑定 this
      • rest[0].push(rest.shift(1))
        var obj = {a: 3}
        Array.prototype.push.call(obj, 4, 5) // 2
        obj // {0: 4, 1: 5, a: 3, length: 2}
        var obj = {a: 3, b: 3}
        Array.prototype.push.call(obj, 4, 5) // 2
        obj //{0: 4, 1: 5, a: 3, b: 3, length: 2}
      

    起源地下载网 » 函数 - 函数反柯里化(uncurrying)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元