js——call、bindとapply、真配列と擬似配列は互いに転換して関数のカリー化となります.

29754 ワード

applyとcall方法の役割:
この2つの方法の用途は特定のスコープ内で関数を呼び出すことであり、実際には関数内のthisオブジェクトの値を設定することに等しい.
書式:call( , 1, 2,...) apply( ,[ ]) : arguments
  • function sum(num1, num2){
        return num1 + num2;
    }
    
    function callSum1(num1, num2){
        //   arguments  
        return sum.apply(this, arguments);
    }
    
    function callSum2(num1, num2){
        //     
        return sum.apply(this, [num1, num2]);
    }
    
    //20
    alert(callSum1(10,10));
    //40
    alert(callSum2(20,20));
    
  • 例2
  • function fun1(...args) {
        console.log(1)
        console.log(...args)
    }
    
    function fun2() {
        console.log(2)
        fun1.call(this, 2, 3)
        fun1.apply(this, [4, 5])
    }
    
    fun2()
    /*
    2
    1
    2 3
    1
    4 5
    */
    
  • 例3
  • //              ,                       
    window.color = 'red'
    let obj = { color: "blue" }
    
    function sayColor() {
        console.log(this.color)
    }
    
    sayColor() // red
    sayColor.call(this) // red
    sayColor.call(window) // red
    sayColor.call(obj) // blue
    
    ビッド
    bind関数は新しいバインディング関数(bound function、BF)を作成します.バインディング関数は、元の関数オブジェクトを包装したexotic function oject(怪しい関数オブジェクト、ECMAScript 2015の用語)です.バインディング関数の呼び出しは、通常、パッケージ関数の実行につながる.
    bindメソッドは、新しい関数を作成し、呼び出し時に、thisキーワードを提供する値に設定します.そして、新しい関数を呼び出したとき、与えられたパラメータリストを元の関数のパラメータシーケンスの最初の項目とします.
    シンタックス
  • thisArgがバインディング関数を呼び出したとき、ターゲット関数にthisパラメータとして伝達される値.new演算子を使用してバインディング関数を作成すると、値を無視します.ビットを使用してsetTimeoutで関数を作成すると(コールバックとして提供される)、thisArg伝達の元の任意の値はobjectに変換される.Bind関数のパラメータリストが空の場合、スコープを実行するthisは、新しい関数のthisArgと見なされます.
  • arg 1,arg 2,…ターゲット関数が呼び出されると、あらかじめバインディング関数のパラメータリストに追加されます.
  • let writen = document.write
    
    writen('hello')// error
    writen.bind(document)('hello')// right
    
    バインディング関数を作成
    var module = {
      x: 42,
      getX: function() {
        return this.x;
      }
    }
    
    var unboundGetX = module.getX;
    console.log(unboundGetX()); // The function gets invoked at the global scope
    // expected output: undefined
    
    var boundGetX = unboundGetX.bind(module);
    console.log(boundGetX());
    // expected output: 42
    
    包装Aray.prototype.slice方法
    function fun() {
        console.log(Array.prototype.slice.call(arguments)) // (3) [1, 2, 3]
    
        let slice = arg => Array.prototype.slice.apply(arg)
        console.log(slice(arguments)) // (3) [1, 2, 3]
    
        //    bind      ,     Array.prototype.slice   
        let unboundSlice = Array.prototype.slice;
        let slice1 = Function.prototype.apply.bind(unboundSlice);
        console.log(slice1(arguments)) // (3) [1, 2, 3]
    }
    
    fun(1, 2, 3)
    
    もっと多くの例を参照してください.
    //    bind
    Function.prototype.myBind = function (oThis, ...args) {
      if (typeof oThis !== 'object') return
      let [_self, func] = [this, function () {}]
    
      let fBind = function () {
        return _self.apply(this instanceof _self ? this : oThis, [...args, ...arguments])
      }
    
      if(_self.prototype){ //       
         func.prototype = _self.prototype
         fBind.prototype = new func()
      }
    
      return fBind
    }
    
    function add (...args) {
      console.log(this.join(' '), args.reduce((a, b) => a + b))
    }
    let obj = ['hello', 'world']
    let fun = add.myBind(obj, 1, 2, 3, 4)
    fun(5) // hello 15
    
    bind、appyとcallの3つの違い
    applyとcallの違いは、伝え方が違っています.
  • appyは、2つのパラメータだけを受信し、対象となるオブジェクトと配列は、この関数の参照
  • である.
  • callは、複数のパラメータを受信し、最初は目標オブジェクトであり、後の値はすべて関数の参照
  • である.
    ビッドと前の二つの違い:
  • bind方法は、すぐに実行されずにコンテキストが変更された関数を実行することに戻り、前の2つは直接に関数を実行することになる.彼のパラメータの形式はコールと同じです.
  • function fun (...args) {
      console.log(args)
    }
    
    let obj = {}
    
    fun.call(obj, 1, 2, 3)// (3) [1, 2, 3]
    fun.apply(obj, [4, 5, 6])// (3) [4, 5, 6]
    let save = fun.bind(obj, 7, 8, 9)//            fun   
    save()// (3) [7, 8, 9]
    
    真の配列と疑似配列は互いに変換されます.
    真配列:function.bind(thisArg[, arg1[, arg2[, ...]]])疑似配列:var arr=[1,2,3,4];(注:最後のレングスは欠かせない)
    /*          */
        	var ar=[1,3,4,5,6];
        	var ob={};
        	/*
        	1、  [].push      push  
        	2、  apply(ob)    push     this         
        	3、             ,     ob
         	*/
        	[].push.apply(ob,ar);//  
        	console.log(ob);/*{0: 1, 1: 3, 2: 4, 3: 5, 4: 6, length: 5}*/
    
    /*          */
            //       
            var res=document.querySelectorAll('div');
            //      
            var obj={0:'lng',1:'af',length:2};
    
            //       
            var arr=[].slice.call(obj);//  
            var arr1=[].slice.call(res);
            /*
             var arr=[];
             [].push.apply(arr,res);//        IE8   
             */
             
            console.log(arr1);//(3) [div, div, div]
            console.log(arr);//(2) ["lng", "af"]
            var arr3=[1,2,3,4];
            console.log(arr3);//(4) [1, 2, 3, 4]
    
    関数コリック化
    function curry(fn) {
        let args = Array.prototype.slice.call(arguments, 1)
        return function () {
            let innerArgs = Array.prototype.slice.call(arguments)
            let finalArgs = args.concat(innerArgs)
            return fn.apply(null, finalArgs)
        }
    }
    
    function add(num1, num2) {
        return num1 + num2
    }
    
    console.log(curry(add, 5)(4)); // 9