JavaScript - 呼び出しと適用、アンチカリーに関するヘルプを求める
淡淡烟草味
淡淡烟草味 2017-05-16 13:41:58
0
2
494

以下は uncurring の 2 つの実装です

1を達成

リーリー

2を達成

リーリー

2 つの結果は同じですが、主にここで 2 番目の実装方法について少し混乱しています

リーリー

すぐにクリックされました、ありがとうございます!

ルイザイ

リーリー
淡淡烟草味
淡淡烟草味

全員に返信(2)
我想大声告诉你

Function.prototype.call.apply(self, arguments);これは少し複雑に見えるかもしれませんが、実際には理解するのは簡単です。
実際、2 番目の実装は、アンチカリーの 3 番目の実装につながる可能性もあります。 リーリー

次に、最初に 2 番目の実装を分析し、次に 3 番目の実装を分析します。実装は次のようになります:

リーリー

uncurrying を呼び出す人は、this または self と等しくなります。これは、self 配列であることを意味します。 Push メソッド

self を置き換え、最後の外部 push は次の関数と同等です:uncurrying,谁就等于thisself. 这意味着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,…)

一貫性のないパラメータ処理を除いて、他の関数は一貫しているため、式をさらに進化させて次を得ることができます:

callapply

式 2

: 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)、それでは:

Array.prototype.push.call(arg1, arg2,…)

式 2

に代入します。これは次と同等です: push([], 1) 就相当于 Array.prototype.push.call([], 1)

答えはすでに明らかで、配列の末尾に数値 1 を追加することです。 [].push(1)


次に、アンチカリーの 3 番目の実装を分析してみましょう:

の場合、全体は次と同等です:

this.call.bind(this);部分,this相当于Array.prototype.push

ここでの難しさは、bind メソッドにあります。bind の実装は、次のように比較的簡単です。 リーリー

理解したいなら、複雑なことを単純化する必要があります。理解するのが簡単であればあるほど、より深く理解できるようになります。 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.prototypecall方法にあります。この場合、次の恒等式が成り立ちます:

リーリー

上記の関数は次と同等になります:

リーリー

置換されたパラメータを削除すると、関数は次のように復元できます:

リーリー

要約すると、アンチカリーの最後の 3 番目の実装は 2 番目の実装と完全に一致します。 気に入っていただけましたら、ぜひ「いいね」を押して、ありがとうございます~

とカレーについての理解を深めるために、それらを深く分析するブログも書きました。 bind

「関数型プログラミングのカリー化とデカリー化」および「Function.prototype.bind メソッド ガイド」を参照してください。

気に入った学生は、私のコラム Lewis のフロントエンド詳細コースもフォローしてください

いいねを押す +0
淡淡烟草味

基本
callとapplyの違いや機能については詳しく説明しません

ソースコード実装の呼び出しと適用
ここでは、呼び出しのみを紹介します。例: a.call(b, c)

  1. 最初のパラメータ x = b を取り出します {}

  2. x.fn = a

  3. 最初のパラメータを除くパラメータをカンマで区切って結合すると、結果は d

  4. 独立した実行環境で関数 e = new Function() を作成し、関数内で x.​​fn(d) を実行します

  5. 作成したeを実行

解決策 2 の理解
オブジェクト メソッドを展開するための call と apply の問題はここでは考慮しません。メソッドはソース コードから動的に作成されるため、この問題については以下で詳しく説明しません。

リーリー
  1. self は Array.prototype.push を指します

  2. (Function.prototype.call).apply(Array.prototype.push, 引数);

  3. 先ほど説明したソース コードを使用して 2 を変換し、Array.prototype.push.(Function.prototype.call)(arguments) を取得します。ここでも呼び出しは配列ではなく変換される必要があります。4 を参照してください。

  4. arguments は配列のようなオブジェクト [arr, 1] です。3 を変換して Array.prototype.push.(Function.prototype.call)(arr, 1) を取得します

  5. callのソースコードは説明されているので、4を変更してarr.(Array.prototype.push)(1)を取得します

  6. もっと詳しく書いてください、arr.push(1)

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート