この記事は、面接の質問における 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 サイトの他の関連記事を参照してください。