Javascript currying柯里化详解

面试题:完成add(1)(2)(3) //效果 = 6,题的中心就是问的js的柯里化

先说说什么是柯里化,看过很多关于柯里化的文章,一直搞不太清晰,比方:柯里化(Currying)是把吸收多个参数的函数变换成吸收一个单一参数(最初函数的第一个参数)的函数,而且返回吸收余下的参数且返回效果的新函数的手艺。大多数的blog都是这类说法,说实话我是懵逼的。
我的邃晓是,curry是一个网络参数的要领,网络够了去实行函数。

完成前我们先列一下要点
1、网络参数(就像面试题屡次实行多个参数)是的应用闭包
2、每次实行参数有多有少比方add(1)(2,3)(4)
3、我们须要晓得什么时候参数够了

        //如题
        //add(1)(2)(3)
        //逻辑应该是如许add(1)实行网络参数1继承实行网络参数2顺次类推直到网络终了。
       function curry(fn) {
            let arg = []; //用于网络参数
            //做一个闭包https://segmentfault.com/a/1190000017824877
            return function() {
                //每实行一次网络一次参数,为什么用concat是由于有时候后是多个参数(2,3)
                arg = arg.concat([...arguments]);
                //直到参数网络完成实行fn
                // 我们须要晓得什么时候网络完了,前提就是curry参数fn的参数个数 fn.length
                //假如网络的参数个数大于即是fn的参数个数实行fn,假如没有递归实行
                if (arg.length >= fn.length) {
                    return fn(...arg)
                }
                // 参数没有网络完我们须要继承网络,递归
                return arguments.callee
            }
        }

        // 测试一下
        let testAdd = curry(add1)
        // console.log(testAdd(1)(2)(3))
        // console.log(testAdd(1, 2)(3))
        //console.log(testAdd(1)(2, 3))

一不小心写完了!

不过不能题目党,说好的详解,接下来我们剖析一下网上大多数柯里化的完成代码

function curry(fn) {
  function _c(restNum, argsList) {
    return restNum === 0 ?
      fn.apply(null, argsList) :
      function(x) {
        return _c(restNum - 1, argsList.concat(x));
      };
  }
  return _c(fn.length, []);
}

一眼看不邃晓没事,我们多看几眼。
剖析:
1、curry也是吸收一个参数(fn)这个是必定
2、返回了一个函数,吸收两个参数,fn.length和一个空数组这个好解
释,我写的简版也说过了,fn.length是为了推断参数是不是网络够
了,参数传一个空数组实在也是闭包的一种完成,用来网络参数。
3、里边是一个三目推断,看着花狸狐哨的没那末庞杂,推断fn的参数个数假如是0,那就没必要网络了直接实行fn,至于fn.apply(null,argList)我很邃晓的高声说出来会用个apply就随处用吗?在我看来没有一分钱用,之所以用是由于argList是一个数组,恰好apply恰好支撑第二个参数是数组,重要看起来很牛逼的模样。
4、网络参数,fn参数个数不为零,每次网络fn函数参数的个数减一,直到即是0实行fn,这个就没有我写的通用了,我一次传俩就挂了。

再来一个例子:bind要领完成

Function.prototype.bind = function(context) {
            //返回一个绑定this的函数,我们须要在此保留this
            let self = this
                // 能够支撑柯里化传参,保留参数
            let arg = [...arguments].slice(1)
                // 返回一个函数
            return function() {
                //一样由于支撑柯里化情势传参我们须要再次猎取存储参数
                let newArg = [...arguments]
                console.log(newArg)
                    // 返回函数绑定this,传入两次保留的参数
                    //斟酌返回函数有返回值做了return
                return self.apply(context, arg.concat(newArg))
            }
        }

        // 搞定测试
        let fn = Person.say.bind(Person1)
        fn()
        fn(18)

是的bind要领就是用的柯里化,bind完成详情请移步:https://segmentfault.com/a/11…

    原文作者:我是一个前端
    原文地址: https://segmentfault.com/a/1190000017998127
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞