JavaScript偏向関数と柯里化実例詳細解

7586 ワード

本論文の実例はJavaScript偏向関数とコリゼーションを述べている.皆さんに参考にしてあげます.具体的には以下の通りです.
今まで私たちは結合についてのみ議論しました.今はもっと深く勉強しましょう.私たちはthisを結合できるだけでなく、パラメータもできます.これは少ないですが、時々便利です.
bind完全な文法は以下の通りです.

let bound = func.bind(context, arg1, arg2, ...);

コンテキストthisと関数の初期パラメータを結びつけることができる.例えば、乗算関数mul(a,b)があります.

function mul(a, b) {
 return a * b;
}

この関数に基づいて、バインディングを使用してdouble関数を作成することができます.

let double = mul.bind(null, 2);
alert( double(3) ); // = mul(2, 3) = 6
alert( double(4) ); // = mul(2, 4) = 8
alert( double(5) ); // = mul(2, 5) = 10

mul.bind(null, 2)を呼び出して、新しい関数doubleを作成し、呼び出しmulの関数を伝達し、第一のパラメータコンテキストをnullと固定し、第二のパラメータを2とし、複数のパラメータ転送も同じである.
これを偏関数応用と呼びます.既存のパラメータ値を固定するための新しい関数を作成します.
注意してください.ここは確かにthisは使いませんが、bindは必要ですので、nullを使わなければなりません.
関数tripleは、以下のコードに3を掛ける機能を実現する.

let triple = mul.bind(null, 3);
alert( triple(3) ); // = mul(3, 3) = 9
alert( triple(4) ); // = mul(3, 4) = 12
alert( triple(5) ); // = mul(3, 5) = 15

なぜ私たちはいつも偏関数を使うのですか?
ここで私たちの偏関数の利点は、名前が分かりやすい独立関数を作成することにより、最初のパラメータに毎回入る必要がないということです.
もう一つは偏り関数を使用する場合、私たちは非常に一般的な関数を持っています.
例えば、関数send(from, to, text)がありますが、バイアス関数を使用して現在のユーザから送信された変形体を作成できます.
コンテキストなしの偏関数を使う
いくつかのパラメータを固定したいのですが、thisはバインドされていませんか?
内蔵sendTo(to, text)は、コンテキストを無視してパラメータにジャンプすることができません.幸いにも、バインディングパラメータbind関数だけが実現しやすい.
以下のとおりです

function partial(func, ...argsBound) {
 return function(...args) { // (*)
  return func.call(this, ...argsBound, ...args);
 }
}
// Usage:
let user = {
 firstName: "John",
 say(time, phrase) {
  alert(`[${time}] ${this.firstName}: ${phrase}!`);
 }
};
// add a partial method that says something now by fixing the first argument
user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
user.sayNow("Hello");
// Something like:
// [10:00] Hello, John!

partialの関数を呼び出した結果、partial(func[, arg1, arg2...])の包装器(*行)を呼び出しました.
  • thisは一致しています.
  • はその後、その…garsBound――partialにこのパラメータ(「10:00」)を使用して呼び出される.
  • その後、パラメータを提供する.…gars――包装器に提供されるパラメータ(「ハロー」)
  • spread演算子を使うと簡単に実現できますか?
    loadasライブラリも提供しました.partialが実現しました.
    コリ化
    上で言及した偏関数と他の名前を混同して「コリゼーション」関数機能と呼ぶ場合がありますが、コリメートは別の面白い処理関数技術です.ここで私たちは関連しなければなりません.
    カリー化(Currying):1つの呼び出し関数funcを変換してuser.sayNowの方式で呼び出します.
    コリメート関数を実現して、二元パラメータ関数、すなわち変換userからf(a,b,c)までを実行しましょう.
    
    function curry(func) {
     return function(a) {
      return function(b) {
       return func(a, b);
      };
     };
    }
    // usage
    function sum(a, b) {
     return a + b;
    }
    let carriedSum = curry(sum);
    alert( carriedSum(1)(2) ); // 3
    
    
    上は一連の包装器で実現しました.
  • f(a)(b)(c)の結果はf(a,b)の一つの包装器です.
  • 呼び出しf(a)(b)がそうであれば、引数はワード環境に保存され、新しい包装器curry(func)
  • に戻る.
  • その後、function(a)は2を提供し、最終的にsum(1)を呼び出し、次いで元のマルチパラメータ関数function(b)に呼び出される.
  • .
    いくつかのコリック化の高度な実装があり、例えば、lodashライブラリ内の_.curryはより複雑な機能を実現することができます.これはパッケージに戻り、すべてのパラメータが正常に呼び出されるか、または偏関数に戻ることができます.
    
    function curry(f) {
     return function(..args) {
      // if args.length == f.length (as many arguments as f has),
      //  then pass the call to f
      // otherwise return a partial function that fixes args as first arguments
     };
    }
    
    
    カリン化?応用シーン?
    アドバンストコリックは、関数が正常に呼び出され、関数が偏りやすくなります.その利点を理解するためには、実際の例を説明する必要があります.
    例えば、ログ関数sum(1)(2)があり、フォーマット出力情報があります.実際のプロジェクトでは、これらの関数は、ネットワークを介して送信またはフィルタリングされるなど、多くの他の有用な特性もあります.
    
    function log(date, importance, message) {
     alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
    }
    
    
    コリ化を使いましょう.
    
    log = _.curry(log);
    
    
    カリー化後も正常に起動できます.
    コリック方式でも呼び出すことができます.function(b)ここで便利な関数を定義して、その日のログを記録します.
    
    // todayLog will be the partial of log with fixed first argument
    let todayLog = log(new Date());
    // use it
    todayLog("INFO", "message"); // [HH:mm] INFO message
    
    
    もう一つの便利な関数を定義します.当日のdebug情報を記録します.
    
    let todayDebug = todayLog("DEBUG");
    todayDebug("message"); // [HH:mm] DEBUG message
    
    
    だから:
    1.カリー化後は何も失われていません.ロゴは正常に呼び出されます.2.複数のシーンで使える便利な偏関数を生成できます.
    高級コリ化実現
    もし興味があれば、ここで上記のような高級なコリック化の実現を提供します.
    
    function curry(func) {
     return function curried(...args) {
      if (args.length >= func.length) {
       return func.apply(this, args);
      } else {
       return function(...args2) {
        return curried.apply(this, args.concat(args2));
       }
      }
     };
    }
    function sum(a, b, c) {
     return a + b + c;
    }
    let curriedSum = curry(sum);
    // still callable normally
    alert( curriedSum(1, 2, 3) ); // 6
    // get the partial with curried(1) and call it with 2 other arguments
    alert( curriedSum(1)(2,3) ); // 6
    
    
    ここで実現するのは複雑そうですが、分かりやすいです.curryの結果は包装機curriedです.次のようになります.
    
    // func is the function to transform
    function curried(...args) {
     if (args.length >= func.length) { // (1)
      return func.apply(this, args);
     } else {
      return function pass(...args2) { // (2)
       return curried.apply(this, args.concat(args2));
      }
     }
    };
    
    
    私達が運行する時、二つの分岐があります.
    1.伝達args数が元の関数で定義されているパラメータの個数と同じか、またはより長い場合は、直接呼び出します.2.偏関数を取得します.そうでなければ、func関数を呼び出しずに別の包装器passに戻り、接続前のパラメータを提供して、新たなパラメータとしてcurriedを再適用します.しかし、再度新しい呼び出しを実行して、新しい偏関数を返します.(パラメータが足りない場合)または最終結果
    例えば、sumがどうなるかを見ましょう.3つのパラメータがあるので、log(date,importance,message).log(new Date(), "DEBUG", "some debug")を呼び出した場合:
    1.第1回の呼び出しlog(new Date())("DEBUG")("some debug"); // log(a)(b)(c)は、語法環境で1を記憶し、リターン包装器sum(a, b, c)を使用する.2.前のパラメータ(1)を持って接続してからsum.length=3を呼び出し、パラメータ数がまだ3未満なので、パスに戻る.3.再度、(3)包装器パスを呼び出し、前のパラメータ(1,2)を持つようにする.その後、3を追加し、curried(1)(2)(3)を呼び出します.最終的には3つのパラメータが元の関数に渡されます.
    まだクリアされていない場合は、呼び出しプロセスを頭や紙に順番に追跡することができます.
    関数パラメータの長さだけ固定
    カリー化は関数が既知のパラメータ数で固定する必要があります.
    カリン化より少し多いです.
    コリゼーションの定義に従って、curried(1)からpassに変換する.
    しかし、Javascriptでは多くの実装が定義を超えています.また、関数に複数のパラメータ変数を使用して実行させてもいいです.
    締め括りをつける
    既知の関数のいくつかのパラメータを固定すると、結果関数は偏関数と呼ばれ、bindを用いて偏関数を得ることによって他の方法でも達成される.
    同じパラメータを一度に繰り返したくないなら、偏関数が便利です.pass関数があります.fromがいつも同じなら、偏関数を使って簡単に呼び出すことができます.
    コリックは、変換関数呼び出しcurried(1,2)からcurried(1,2,3)までであり、Javascriptは通常、正常な呼び出しを実現しても、パラメータの数が足りない場合の偏り関数方式の呼び出しを実現する.
    簡単な偏り関数を考えると、コリック化が非常に良いです.私たちが見たログの例:一般的な関数はsum(a,b,c)、カリー化後に偏り関数が得られます.一つのパラメータはsum(a)(b)(c)、または二つのパラメータsend(from,to)です.
    JavaScriptの関連内容については、当駅のテーマを見ることができます.「JavaScript常用関数技術まとめ」、「javascript対象入門教程」、「JavaScriptエラーとデバッグ技術まとめ」、「JavaScriptデータ構造とアルゴリズム技法まとめ」及び「JavaScript数学演算用法まとめ」
    本論文で述べたように、JavaScriptプログラムの設計に役に立ちます.