JavaScriptの関数バインディングと関数コリック化(高級関数)


関数バインディング
JavaScriptの高度な技術の中に関数バインディングという技術があります.
関数バインディングは、特定のthis環境でパラメータを指定して別の関数を呼び出す関数を作成します.これは、変数として機能を伝達するときにコードを保持するために、関数のコールバックとイベントハンドラと一緒によく使われます.
実行環境
ここで作成した関数は、結合した後に戻ってくる関数で、呼び出されたもう一つの関数は元の関数です.
bind()方法によるバインディングの実現
この方法の主な役割は将
関数をオブジェクトに結合します.質に入れる
関数fn()において、bind()法を用いて、一つのオブジェクトoをパラメータとして導入すると、この方法は新しい関数を返します.
この新しい関数を呼び出すと元の関数fnをオブジェクトoとして呼び出す方法があります.
新しい関数が導入された任意のパラメータは、元の関数に伝えられます.
//          
function fn (y) {
    return this.x + y;
}

//         
var o = {
    x: 2
};

// fn(     o ,        。
var g = fn.bind(o); //  this      o

//    g(x)   o.fn(x)
g(2); //4 2 + 2 = 4
fn()関数をオブジェクトoに結びつけると、thisオブジェクトは、結合関数におけるthis.xの値がオブジェクトoの属性xの値であるため、オブジェクトoを指します.
apply()方法でバインディングを実現します.
上記の例は、bind()方法の存在を決定する場合に定義され、bind()方法が存在するかどうかを判断できない場合、以下の方法を使用して関数をバインディングすることができる.
function bind (f, o) {
    if (f.bind) { //  bind()    ,  bind()             (f.bind(o))
        return f.bind(o);
    } else {
        return function () {
            return f.apply(o, argument); //  bind()     ,     fn()     o 。
        }; 
    }
}
以上から分かるように、「f.apply(o,argment)」の効果は「f.bind(o)」の効果と同じです.この中で、argmentオブジェクトは内部関数です.
この結合関数による方法の例を示します.


  

  
     function bind (f, o) {
         if (f.bind) { //  bind()    ,  bind()             (f.bind(o))
             return f.bind(o);
         } else {
             return function () {
                 return f.apply(o, argument); //  bind()     ,     f     o 。
             }; 
         }
     }
     
     var handler = {
         message: "hello JavaScript",
         
         handClick: function (e) {
             alert(this.message + ":" + e.type);
         }
     };
     
     var input1 = document.querySelector("#input1");
     //this   handler,  this    handler  
     input1.addEventListener("click", bind(handler.handClick, handler)); //hello JavaScript:click
 

ここで、handler.handle Click方法をhandlerオブジェクトに結びつけると、thisの値はhandlerであり、this.messageはhandle.messageであり、hander.handle Click()の実行環境を保持する.
もちろん、直接bind()の方が簡単であれば、イベントハンドラを追加するだけで次のコードに修正する必要があります.
input1.addEventListener("click", handler.handClick.bind(hanlder)); //  this    hanlder。
関数バインディングの使用環境:関数ポインタ(すなわち元の関数ポインタ)を値の形で伝達すると同時に、関数は特定の環境で実行される必要があり、関数バインディングを使用することができます.これらは主にイベントハンドラ、set Timeout()、setinterval()タイマなどに用いられます.
関数コリック化
関数コリック化の方法は関数バインディングと同じで、唯一の違いは
関数カリー化によって作成された関数は、いくつかのパラメータを入力する必要があります.
アプリ()で実現
動的にコリメート関数を作成します.他の関数を呼び出して、コリメートの関数と必要なパラメータを入力します.
function curry (fn) {
    //           ,  curry()              ,        。
    var args = Array.prototype.slice.call(arguments, 1);
    //        ,          
    return function () {
        //             
        var innerArgs = Array.prototype.slice.call(arguments);
        //   、              
        var finalArgs = args.concat(innerArgs);
        //    fn()  ,              。
        return fn.apply(null, finalArgs);
    }
}

//            ,       
function oldSum (num1, num2) {
    return num1 + num2;
}

//     ,        
var newSum = curry(oldSum, 3); // newSum = function () {};
console.log(newSum(4)); //7 3 + 4 = 7
ここの関数は以下のステップを経ています.
第一歩:カリー関数、そして新しい関数を返します.「var oldSum=curry(oldSum、3)」
1、args=[3]は、外部関数がcurry()であり、2番目のパラメータ「3」を配列argsに残しました.アーグメンントオブジェクトが関数に入ってくる複数の実参照にアクセスできることを知っています.ここでは「3」という実パラメータについてアークス配列に保存されています.
2、return function(){}
第二ステップ:newSumを呼び出す(4)
1、inneargs=[4]は、内部関数newSumのパラメータ「4」をinneneargsに保持します.
2、外部、内部関数のパラメータ数はオペレータconcatで一つの配列につづり合わせてfinalArgsに保存します.
3、fn.apply(null,finalArgs)=>fn(finalArgs)=>oldSum(3,4)
結果は7です.
curry関数のために複数の実参照に入ることもできる.
var newSum = curry(oldSum, 4, 6)
conlole.log(newSum(2)); // 10
この時、外部関数パラメータはそれぞれ「4」と「6」があり、新しい関数newSum()を通じて元の関数oldSum()に入った実パラメータは3つありますが、oldSum()は2つのイメージしかないので、内部関数(つまりnewSum)の実パラメータは無視され、元の関数「4」と「6」の2つのパラメータにのみ入力されます.
bind()方法によりコリメート関数を実現します.
bind()方法は、関数を一つのオブジェクトに結びつけるだけでなく、他の効果もある.
最初の実証に加えて,着信bind()法の実証もthisオブジェクトに結合され,ここでのthisの値は着信bind()法のオブジェクトまたは関数に結合される.ビッド()方法によってコリック化を実現する方法は、thisの値の後にもう一つのパラメータを入力すればいいです.bind()方法実現:


  


    function bind (f, o) {
        if (f.bind) { //  bind()    ,  bind()             (f.bind(o))
            return f.bind(o);
        } else {
            return function () {
                return f.apply(o, argument); //  bind()     ,     f     o 。
            }; 
        }
    }
    
    var handler = {
        message: "hello JavaScript",
        
        handClick: function (e) {
            alert(this.message + ":" + e.type);
        }
    };
    
    var input1 = document.querySelector("#input1");
    //this   handler,           ,        。
    input1.addEventListener("click", handler.handClick(handler, "input1")); //hello JavaScript:click


ここではthisの値である「handler」の後にもう一つのパラメータ「input 1」が入ってきて、このボタンを表します.こうしてコリメート関数が実現されました.
追加例:
var oldSum = function (x, y) {
    return x + y;
};

//      oldSum   , this     null。
//          1,               
var newSum = oldSum.bind(null, 1); //    1     x 

newSum(2); //3 x   1,   2    y。

function f (y, z) {
    return this.x + y + z;
}

var g = f.bind({x: 1}, 2); //this    x,2   y 。

g(4); //7 this.x  1,y   2,z   4。
追加例:
function oldSum (num1, num2) {
    return num1 + num2;
}

var o = {
    num1: 1
};

var newSum1 = oldSum.bind(this, 2); //this.oldSum(2)   2      num1 。

console.log(newSum1(3)); //5 num1  2,num2  3。



function oldSum (num1, num2) {
    return num1 + num2;
}

var o = {
    num1: 1
};

var newSum1 = oldSum.bind(this, 2,4); //this.oldSum(2)   2      num1 ,4    num2 

console.log(newSum1(3)); //6 num1  2,num2  4,                  。
この時、
オリジナル関数の参照数が増加しました.
新しい関数の参照は、元の関数の参照にも結合されます.
function oldSum (num1, num2, num3) {
    return num1 + num2j + num3;
}

var o = {
    num1: 1
};

var newSum1 = oldSum.bind(this, 2, 4); //this.oldSum(2)   2      num1 ,4   num2 

console.log(newSum1(3)); //9 num1  2,num2  4,num3  3
次に、入力bind()方法の実装値が1つ減少する.
function oldSum (num1, num2, num3) {
    return num1 + num2j + num3;
}

var o = {
    num1: 1
};

var newSum1 = oldSum.bind(this, 2); //this.oldSum(2)   2      num1 。

console.log(newSum1(3, 5)); //10 num1  2,num2  2,num3  5
上記のいくつかの例から,着信bind()法の実証は,最初の関数に相当するバインディング関数のイメージアップに優先的に結合されていることがわかった.ビnd()法に導入された実パラメータの数が結合関数の形パラメータの数より多い場合、1つずつ対応すると、最後のいくつかの実参照が無視される.ビnd()法に導入された実パラメータの数が結合関数の形の数より少ない場合、実際の参照は最初のいくつかの形の参照に結合され、残りの形の結合の新しい関数が入ってきた実参照の場合、この時に新しい関数が入ってきた複数の残りの形の個数が、それぞれ対応する場合、新しい関数の最後のいくつかの実参照を無視する.
bind()メソッドは、関数オブジェクトを返します.この関数の
length値(新しい関数が入力できる実数)は、
結合関数の変形個数から結合関数の実パラメータ(すなわち、bind()法から入ってきた実パラメータ個数)の個数を減算します.
function oldSum (num1, num2, num3) {
    return num1 + num2j + num3;
}

var o = {
    num1: 1
};

var newSum1 = oldSum.bind(this, 2); //this.oldSum(2)   2      num1 。

console.log(newSum1(3, 5)); //10 num1  2,num2  2,num3  5
ここで、バインディング関数の変形個数は3であり、バインディング関数の実パラメータ個数(すなわち、bind()方法で導入された実パラメータの個数)は1であり、新関数が導入できる実パラメータの個数は3−1=2であり、つまり、「3」と「5」の2つの実参照に入ることができる.
もし
bind()メソッドから返された関数の構造関数は,bind()に入ってくるthisを無視して,元の関数は構造関数として呼び出され,実際のパラメータは元の関数にそのまま入ってきます.bind()メソッドで返された関数にはプロトタイプ属性は含まれておらず、bind()メソッドで返された関数は、コンストラクタとして作成されたオブジェクトがバインディングされていない関数としてプロトタイプ属性を継承します.
関数結合と関数コリック化の違い:コリック化は結合関数に基づいて、this値の後に実務参に入る.