首頁 > web前端 > js教程 > 面試題中Javascript currying柯里化的詳細理解

面試題中Javascript currying柯里化的詳細理解

不言
發布: 2019-01-24 09:51:30
轉載
2367 人瀏覽過

這篇文章帶給大家的內容是關於面試題中Javascript currying柯里化的詳細理解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

面試題:實作add(1)(2)(3) //結果=  6,題的核心就是問的js的柯里化

先說說什麼是柯里化,看過許多關於柯里化的文章,始終搞不太清楚,例如:柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且傳回接受餘下的參數且傳回結果的新函數的技術。大多數的blog都是這種說法,說實話我是懵逼的。
我的理解是,curry是一個收集參數的方法,收集夠了去執行函數。

實現前我們先列一下要點
1、收集參數(就像面試題多次執行多個參數)是的利用閉包
2、每次執行參數有多有少例如add(1)(2,3)(4)
3、我們需要知道什麼時候參數夠了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

        //如题

        //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))

登入後複製

一不小心寫完了!

不過不能標題黨,說好的詳解,接下來我們解析一下網上大多數柯里化的實現代碼

1

2

3

4

5

6

7

8

9

10

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方法實作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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方法就是用的柯里化。

以上是面試題中Javascript currying柯里化的詳細理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板