以下は uncurring の 2 つの実装です
1を達成
2を達成
2 つの結果は同じですが、主にここで 2 番目の実装方法について少し混乱しています
すぐにクリックされました、ありがとうございます!
ルイザイ
Function.prototype.call.apply(self, arguments);これは少し複雑に見えるかもしれませんが、実際には理解するのは簡単です。 実際、2 番目の実装は、アンチカリーの 3 番目の実装につながる可能性もあります。 リーリー
Function.prototype.call.apply(self, arguments);
リーリー
uncurrying
this
self
配列であることを意味します。 Push メソッド
self を置き換え、最後の外部 push は次の関数と同等です:uncurrying,谁就等于this或self. 这意味着self就是数组的push方法.替换掉self,最终外部的push リーリー ここに
push
数组的push方法
には配列をパラメータに分解する機能があることを理解しましょう。 apply函数,apply
apply
導出式:a.apply(b, arguments) 意味着把b当做this上下文,相当于是在b上调用a方法,并且传入所有的参数,如果b中本身就含有a方法,那么就相当于 b.a(arg1, arg2,…)
a.apply(b, arguments)
b.a(arg1, arg2,…)
式 1:a.apply(b, arguments) === b.a(arg1, arg2,…)
a.apply(b, arguments) === b.a(arg1, arg2,…)
call 和 apply
call
: a.call(b, arg) === b.a(arg)式 1
a.call(b, arg) === b.a(arg)
つまり、a は call メソッドと同じです。
次に数式を代入すると、次のようになります: a = Function.prototype.call
a = Function.prototype.call
つまり、b は配列のプッシュメソッドと同じです
すると、b = Array.prototype.pushは次と相対関係になります:
b = Array.prototype.push
Function.prototype.call.apply(Array.prototype.push, arguments)、それでは:
Function.prototype.call.apply(Array.prototype.push, arguments)
Array.prototype.push.call(arg1, arg2,…) を
Array.prototype.push.call(arg1, arg2,…)
に代入します。これは次と同等です: push([], 1) 就相当于 Array.prototype.push.call([], 1)
push([], 1)
Array.prototype.push.call([], 1)
答えはすでに明らかで、配列の末尾に数値 1 を追加することです。 [].push(1)
[].push(1)
の場合、全体は次と同等です:
this.call.bind(this);部分,this相当于Array.prototype.push
this.call.bind(this);
Array.prototype.push
理解したいなら、複雑なことを単純化する必要があります。理解するのが簡単であればあるほど、より深く理解できるようになります。 Array.prototype.push.call.bind(Array.prototype.push) をさらに単純化するには、新しい関数を返すだけです。
Array.prototype.push.call.bind(Array.prototype.push)
関数
リーリー bind的原理,等同于谁调用bind上記は
bind
Array.prototype.push.call.bind(Array.prototype.push) は次と同等になります:
これは、アンチカリーの 2 番目の実装とは少し異なりますが、表面的には一貫性がないように見えますが、本質的には一貫しています。しばらくお待ちください。以下をお読みください:
違いは前半のArray.prototype.push.call,这里它是一个整体,实际上想代表的就是call方法。而我们都知道,所有函数的call方法,最终都是Function.prototype 的 call方法にあります。この場合、次の恒等式が成り立ちます:
Array.prototype.push.call
Function.prototype
上記の関数は次と同等になります:
置換されたパラメータを削除すると、関数は次のように復元できます:
要約すると、アンチカリーの最後の 3 番目の実装は 2 番目の実装と完全に一致します。 気に入っていただけましたら、ぜひ「いいね」を押して、ありがとうございます~
とカレーについての理解を深めるために、それらを深く分析するブログも書きました。 bind
基本callとapplyの違いや機能については詳しく説明しません
ソースコード実装の呼び出しと適用ここでは、呼び出しのみを紹介します。例: a.call(b, c)
最初のパラメータ x = b を取り出します {}
x.fn = a
最初のパラメータを除くパラメータをカンマで区切って結合すると、結果は d
独立した実行環境で関数 e = new Function() を作成し、関数内で x.fn(d) を実行します
作成したeを実行
解決策 2 の理解 オブジェクト メソッドを展開するための call と apply の問題はここでは考慮しません。メソッドはソース コードから動的に作成されるため、この問題については以下で詳しく説明しません。
self は Array.prototype.push を指します
(Function.prototype.call).apply(Array.prototype.push, 引数);
先ほど説明したソース コードを使用して 2 を変換し、Array.prototype.push.(Function.prototype.call)(arguments) を取得します。ここでも呼び出しは配列ではなく変換される必要があります。4 を参照してください。
arguments は配列のようなオブジェクト [arr, 1] です。3 を変換して Array.prototype.push.(Function.prototype.call)(arr, 1) を取得します
callのソースコードは説明されているので、4を変更してarr.(Array.prototype.push)(1)を取得します
もっと詳しく書いてください、arr.push(1)
次に、最初に 2 番目の実装を分析し、次に 3 番目の実装を分析します。実装は次のようになります:Function.prototype.call.apply(self, arguments);
これは少し複雑に見えるかもしれませんが、実際には理解するのは簡単です。実際、2 番目の実装は、アンチカリーの 3 番目の実装につながる可能性もあります。 リーリー
リーリー
uncurrying
を呼び出す人は、this
またはself
と等しくなります。これは、self
が配列であることを意味します。 Push メソッド
。self
を置き換え、最後の外部push
は次の関数と同等です:uncurrying
,谁就等于this
或self
. 这意味着self
就是数组的push方法
.替换掉
self
,最终外部的push
リーリー ここにには配列をパラメータに分解する機能があることを理解しましょう。
apply
函数,apply
導出式:
a.apply(b, arguments)
意味着把b当做this上下文,相当于是在b上调用a方法,并且传入所有的参数,如果b中本身就含有a方法,那么就相当于b.a(arg1, arg2,…)
式 1:
一貫性のないパラメータ処理を除いて、他の関数は一貫しているため、式をさらに進化させて次を得ることができます:a.apply(b, arguments) === b.a(arg1, arg2,…)
call
和apply
:
を上記の関数に代入すると、次のようになります:a.call(b, arg) === b.a(arg)
式 1つまり、a は call メソッドと同じです。
次に数式を代入すると、次のようになります:
a = Function.prototype.call
つまり、b は配列のプッシュメソッドと同じです
すると、
b = Array.prototype.push
は次と相対関係になります:Function.prototype.call.apply(Array.prototype.push, arguments)
、それでは:
式 2Array.prototype.push.call(arg1, arg2,…)
をに代入します。これは次と同等です:
push([], 1)
就相当于Array.prototype.push.call([], 1)
答えはすでに明らかで、配列の末尾に数値 1 を追加することです。
[].push(1)
次に、アンチカリーの 3 番目の実装を分析してみましょう:
の場合、全体は次と同等です:
ここでの難しさは、bind メソッドにあります。bind の実装は、次のように比較的簡単です。 リーリーthis.call.bind(this);
部分,this
相当于Array.prototype.push
理解したいなら、複雑なことを単純化する必要があります。理解するのが簡単であればあるほど、より深く理解できるようになります。
Array.prototype.push.call.bind(Array.prototype.push)
をさらに単純化するには、新しい関数を返すだけです。関数
がパラメーターをバインドし、最終的に以下を返すと仮定します。リーリー
となり、次のようになります:bind
的原理,等同于谁调用bind
上記は
リーリーArray.prototype.push.call.bind(Array.prototype.push)
は次と同等になります:これは、アンチカリーの 2 番目の実装とは少し異なりますが、表面的には一貫性がないように見えますが、本質的には一貫しています。しばらくお待ちください。以下をお読みください:
違いは前半の
リーリーArray.prototype.push.call
,这里它是一个整体,实际上想代表的就是call方法。而我们都知道,所有函数的call方法,最终都是Function.prototype
的call
方法にあります。この場合、次の恒等式が成り立ちます:上記の関数は次と同等になります:
リーリー置換されたパラメータを削除すると、関数は次のように復元できます:
リーリー要約すると、アンチカリーの最後の 3 番目の実装は 2 番目の実装と完全に一致します。 気に入っていただけましたら、ぜひ「いいね」を押して、ありがとうございます~
。とカレーについての理解を深めるために、それらを深く分析するブログも書きました。
「関数型プログラミングのカリー化とデカリー化」および「Function.prototype.bind メソッド ガイド」を参照してください。bind
基本
callとapplyの違いや機能については詳しく説明しません
ソースコード実装の呼び出しと適用
ここでは、呼び出しのみを紹介します。例: a.call(b, c)
最初のパラメータ x = b を取り出します {}
x.fn = a
最初のパラメータを除くパラメータをカンマで区切って結合すると、結果は d
独立した実行環境で関数 e = new Function() を作成し、関数内で x.fn(d) を実行します
作成したeを実行
解決策 2 の理解
リーリーオブジェクト メソッドを展開するための call と apply の問題はここでは考慮しません。メソッドはソース コードから動的に作成されるため、この問題については以下で詳しく説明しません。
self は Array.prototype.push を指します
(Function.prototype.call).apply(Array.prototype.push, 引数);
先ほど説明したソース コードを使用して 2 を変換し、Array.prototype.push.(Function.prototype.call)(arguments) を取得します。ここでも呼び出しは配列ではなく変換される必要があります。4 を参照してください。
arguments は配列のようなオブジェクト [arr, 1] です。3 を変換して Array.prototype.push.(Function.prototype.call)(arr, 1) を取得します
callのソースコードは説明されているので、4を変更してarr.(Array.prototype.push)(1)を取得します
もっと詳しく書いてください、arr.push(1)