ホームページ  >  記事  >  ウェブフロントエンド  >  面接の質問における Javascript カリー化についての詳細な理解

面接の質問における Javascript カリー化についての詳細な理解

不言
不言転載
2019-01-24 09:51:302243ブラウズ

この記事は、面接の質問における Javascript のカリー化について詳しく説明しています。必要な方は参考にしていただければ幸いです。

インタビューの質問: add(1)(2)(3) を実装 //結果 = 6、質問の核心は js のカリー化です

まず、カリー化とは何かについて話しましょう。 , カリー化に関する多くの記事を読みましたが、まだ理解できません。例: カリー化は、複数のパラメーターを受け入れる関数を、単一のパラメーター (元の関数の最初のパラメーター) を受け入れる関数に変換して返します。残りのパラメーターを受け入れ、結果を返す新しい関数。ほとんどのブログにはそう書かれていますが、正直言って私は混乱しています。
私の理解では、カレーはパラメータを収集する方法であり、十分な数が収集された場合に関数が実行されます。

実装の前に重要なポイントを列挙しましょう
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. カリーはパラメータ (fn) も受け取ります。これは必然です。これは関数を返し、fn.length と空の配列を受け取ります。 .
説明 、私が書いた簡略版で述べたように、 fn.length はパラメータが十分に収集されたかどうかを判断するために使用され、実際にはパラメータを収集するために使用されるクロージャの実装です。
3. 内部には三眼判定があります。見た目は派手ですが、fn を判定するためのパラメータの数が 0 の場合は、fn.apply(null と同様) を直接実行する必要はありません。 ,argList) I はっきりと声に出して言えば、応用してどこにでも使えますか?私の意見では、これが使用される理由は、argList が配列であり、apply が 2 番目のパラメーターが配列であることをサポートしているだけであるためです。
4. fn パラメータの数は 0 ではありません。fn 関数のパラメータの数が 0 になるまで 1 ずつ減らして、fn を実行します。 2匹同時に通り過ぎて死んでしまいました。

別の例: バインド メソッドの実装

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)

はい、バインド メソッドはカリー化を使用します。

以上が面接の質問における Javascript カリー化についての詳細な理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。