コリー化関数の実現解析について
3242 ワード
この記事は主に以下の記事を参考にしています.
sum(2)(3)==sum(2,3)からコリー化関数の実現まで
JavaScriptの特定のテーマの関数のコリー化
コリー定義
数学とコンピュータ科学では,コリー化は複数のパラメータを用いた1つの関数を1つのパラメータを用いた一連の関数に変換する技術である.
コリー化関数の実現
以上の2つの文章の中で,両著者はコリー化関数の実現方式を比較的詳細に分析し,特に冴羽の文章ではゼロからコリー化関数を実現する方法を詳細に示しているが,ここではこれ以上述べることはない.
ここでは主に上の最初の文章の実現方法について、実行過程の分析を行います.主にその中の具体的ないくつかの実行過程に対して単独でコードを見るかまだよく分からないので、特に詳しく分析を実行して理解して、記憶を深めます.
インプリメンテーションモード
この方法は私が一番受け入れやすいと思います.
いくつかの異なるパラメータ方式の実行過程をそれぞれ見てみましょう.
sum(1,2,3,4)
sum(1,2,3)(4)
sum(1,2)(3,4)
いくつかのパラメータ伝達方式の実行過程の解析から,いくつかの重要な変数の内容を明確に見ることができ,コリー化関数の実行過程を明確に理解することができる.
パーソナル最適化
以上の実行方式について,コリー化された関数のほかに,この関数のパラメータ数に基づいて対応する数の値を伝達する必要があることが分かるが,これはそれほど便利ではない.改善してみてはいかがでしょうか
ここではlength属性を用いて関数のパラメータ個数を指定することによって,コリー化された関数のパラメータ数を取得し,追加の伝達を必要としない.しかし、この場合、コリー化された関数のパラメータにはデフォルト値がないことに注意してください.そうしないと、length属性は意味がありません.だからこの方法も完璧ではありません.
小結
簡単に言えば、コリー化関数を実現する方法は基本的にパラメータと再帰的な方法に基づいて実現する必要があります.そうすれば、パラメータを分割する方法でマルチパラメータの関数方法を呼び出すことができます.このような利点は,繰返し伝達の不変部分パラメータを低減し,コリー化後のcallbackパラメータをmap,filterなどの関数に伝達することである.
しかし、これは非常に高度な使い方であり、一般的な開発シーンではあまり使われていないことも認めざるを得ない.
sum(2)(3)==sum(2,3)からコリー化関数の実現まで
JavaScriptの特定のテーマの関数のコリー化
コリー定義
数学とコンピュータ科学では,コリー化は複数のパラメータを用いた1つの関数を1つのパラメータを用いた一連の関数に変換する技術である.
コリー化関数の実現
以上の2つの文章の中で,両著者はコリー化関数の実現方式を比較的詳細に分析し,特に冴羽の文章ではゼロからコリー化関数を実現する方法を詳細に示しているが,ここではこれ以上述べることはない.
ここでは主に上の最初の文章の実現方法について、実行過程の分析を行います.主にその中の具体的ないくつかの実行過程に対して単独でコードを見るかまだよく分からないので、特に詳しく分析を実行して理解して、記憶を深めます.
インプリメンテーションモード
この方法は私が一番受け入れやすいと思います.
function curry(fn, argLen, currArgs) {
return function() {
console.log("arguments:", arguments, arguments.length)
var args = [].slice.call(arguments);
console.log("args:", args)
//
if (currArgs !== undefined) {
args = args.concat(currArgs);
}
//
if (args.length == argLen) {
return fn.apply(this, args);
} else {
return curry(fn, argLen, args);
}
}
}
function sumOf(a, b, c, d) {
return a + b + c + d;
}
// ,
var sum = curry(sumOf, 4);
いくつかの異なるパラメータ方式の実行過程をそれぞれ見てみましょう.
sum(1,2,3,4)
>sum(1,2,3,4)
arguments: Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ] 4
args: (4) [1, 2, 3, 4]
sum(1,2,3)(4)
>sum(1,2,3)(4)
arguments: Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ] 3
args: (3) [1, 2, 3]
arguments: Arguments [4, callee: ƒ, Symbol(Symbol.iterator): ƒ] 1
args: [4]
sum(1,2)(3,4)
>sum(1,2)(3,4)
arguments: Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ] 2
args: (2) [1, 2]
arguments: Arguments(2) [3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ] 2
args: (2) [3, 4]
いくつかのパラメータ伝達方式の実行過程の解析から,いくつかの重要な変数の内容を明確に見ることができ,コリー化関数の実行過程を明確に理解することができる.
パーソナル最適化
以上の実行方式について,コリー化された関数のほかに,この関数のパラメータ数に基づいて対応する数の値を伝達する必要があることが分かるが,これはそれほど便利ではない.改善してみてはいかがでしょうか
function curry(fn, currArgs) {
return function() {
console.log("arguments:", arguments, arguments.length)
var args = [].slice.call(arguments);
console.log("args:", args)
//
if (currArgs !== undefined) {
args = args.concat(currArgs);
}
//
if (args.length == fn.length) {
return fn.apply(this, args);
} else {
return curry(fn, args);
}
}
}
ここではlength属性を用いて関数のパラメータ個数を指定することによって,コリー化された関数のパラメータ数を取得し,追加の伝達を必要としない.しかし、この場合、コリー化された関数のパラメータにはデフォルト値がないことに注意してください.そうしないと、length属性は意味がありません.だからこの方法も完璧ではありません.
小結
簡単に言えば、コリー化関数を実現する方法は基本的にパラメータと再帰的な方法に基づいて実現する必要があります.そうすれば、パラメータを分割する方法でマルチパラメータの関数方法を呼び出すことができます.このような利点は,繰返し伝達の不変部分パラメータを低減し,コリー化後のcallbackパラメータをmap,filterなどの関数に伝達することである.
var persons = [{name: 'kevin', age: 11}, {name: 'daisy', age: 24}]
let getProp = _.curry(function (key, obj) {
return obj[key]
});
let names2 = persons.map(getProp('name'))
console.log(names2); //['kevin', 'daisy']
let ages2 = persons.map(getProp('age'))
console.log(ages2); //[11,24]
しかし、これは非常に高度な使い方であり、一般的な開発シーンではあまり使われていないことも認めざるを得ない.