918

私はすでにそれを知ってapplyおり、(関数のコンテキスト)callを設定する同様の関数です。this

違いは、引数の送信方法(手動と配列)にあります

質問:

しかし、いつこの bind()方法を使用する必要がありますか?

var obj = {
  x: 81,
  getX: function() {
    return this.x;
  }
};

alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));

jsbin

4

23 に答える 23

861

その関数を後で特定のコンテキストで呼び出して、イベントで役立つようにする場合に使用.bind()します。.call()またはを使用.apply()して、関数をすぐに呼び出し、コンテキストを変更します。

関数をすぐに呼び出す/適用しますがbind、後で実行されると、元の関数を呼び出すための正しいコンテキストが設定される関数を返します。このようにして、非同期コールバックとイベントのコンテキストを維持できます。

私はこれをたくさんします:

function MyObject(element) {
    this.elm = element;

    element.addEventListener('click', this.onClick.bind(this), false);
};

MyObject.prototype.onClick = function(e) {
     var t=this;  //do something with [t]...
    //without bind the context of this function wouldn't be a MyObject
    //instance as you would normally expect.
};

Node.jsで、メンバーメソッドを渡したい非同期コールバックに広く使用していますが、コンテキストを非同期アクションを開始したインスタンスにする必要があります。

バインドの単純で単純な実装は次のようになります。

Function.prototype.bind = function(ctx) {
    var fn = this;
    return function() {
        fn.apply(ctx, arguments);
    };
};

(他の引数を渡すなど)それ以上のものがありますが、それについてもっと読んで、MDNでの実際の実装を見ることができます。

于 2013-03-16T21:44:40.687 に答える
490

それらはすべてこれを関数 (またはオブジェクト) にアタッチしますが、違いは関数の呼び出しにあります (以下を参照)。

call はこれを関数にアタッチし、すぐに関数を実行します:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"

bindはこれを関数にアタッチし、次のように個別に呼び出す必要があります。

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
var helloFunc = person.hello.bind({ name: "Jim Smith" });
helloFunc("world");  // output: Jim Smith says hello world"

またはこのように:

...    
var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world");
helloFunc();  // output: Jim Smith says hello world"

applyはcallに似ていますが、一度に 1 つずつ引数をリストするのではなく、配列のようなオブジェクトを取る点が異なります。

function personContainer() {
  var person = {  
     name: "James Smith",
     hello: function() {
       console.log(this.name + " says hello " + arguments[1]);
     }
  }
  person.hello.apply(person, arguments);
}
personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"                                     
于 2015-08-10T14:50:45.233 に答える
76

TL;DR:

簡単に言えば、バインドは関数を作成し、呼び出しと適用は関数を実行しますが、適用は配列内のパラメーターを期待します

完全な説明

multiplication関数があると仮定します

function multiplication(a,b){
console.log(a*b);
}

を使用していくつかの標準関数を作成しましょうbind

var multiby2 = multiplication.bind(this,2);

ここで、multiby2(b) は multiplication(2,b) と等しくなります。

multiby2(3); //6
multiby2(4); //8

バインドで両方のパラメーターを渡すとどうなりますか

var getSixAlways = multiplication.bind(this,3,2);

これで、getSixAlways() は乗算 (3,2) と等しくなります。

getSixAlways();//6

パラメーターを渡しても 6 が返されます。 getSixAlways(12); //6

var magicMultiplication = multiplication.bind(this);

これにより、新しい乗算関数が作成され、magicMultiplication に割り当てられます。

いいえ、乗算機能を magicMultiplication に隠しています。

呼び出し magicMultiplicationは空白を返しますfunction b()

実行すると正常に動作します magicMultiplication(6,5); //30

電話して申し込んでみてはどうですか?

magicMultiplication.call(this,3,2); //6

magicMultiplication.apply(this,[5,2]); //10

于 2015-06-10T18:04:20.110 に答える
56

this関数の呼び出し方法に関係なく、値を設定できます。これは、コールバックを操作するときに非常に便利です。

  function sayHello(){
    alert(this.message);
  }

  var obj = {
     message : "hello"
  };
  setTimeout(sayHello.bind(obj), 1000);

で同じ結果を得るには、次のcallようになります。

  function sayHello(){
    alert(this.message);
  }

  var obj = {
     message : "hello"
  };
  setTimeout(function(){sayHello.call(obj)}, 1000);
于 2013-03-16T21:45:01.677 に答える
35

と の両方で、指定された値で関数Function.prototype.call()Function.prototype.apply()呼び出し、thisその関数の戻り値を返します。

Function.prototype.bind()一方、指定されたthis値で新しい関数を作成し、その関数を実行せずに返します。

それでは、次のような関数を考えてみましょう:

var logProp = function(prop) {
    console.log(this[prop]);
};

では、次のようなオブジェクトを考えてみましょう。

var Obj = {
    x : 5,
    y : 10
};

次のように、関数をオブジェクトにバインドできます。

Obj.log = logProp.bind(Obj);

Obj.logこれで、コード内のどこでも実行できます:

Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10

this本当に興味深いのは、 の値だけでなく、その引数の値もバインドする場合ですprop

Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');

これを行うことができます:

Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
于 2016-01-18T03:59:16.087 に答える
26

bind : 指定された値とコンテキストで関数をバインドしますが、関数は実行しません。関数を実行するには、関数を呼び出す必要があります。

call : 提供されたコンテキストとパラメーターを使用して関数を実行します。

apply : 指定された context と parameter を array として関数を実行します。

于 2017-11-22T17:31:46.177 に答える
20

、との違いを説明する1 つの良い記事を次に示します。要約すると、次のようになります。bind()apply()call()

  • bind()関数またはメソッドが呼び出されたときに、どの特定のオブジェクトがこれにバインドされるかを簡単に設定できます。

    // This data variable is a global variable​
    var data = [
        {name:"Samantha", age:12},
        {name:"Alexis", age:14}
    ]
    var user = {
        // local data variable​
        data    :[
            {name:"T. Woods", age:37},
            {name:"P. Mickelson", age:43}
        ],
        showData:function (event) {
            var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1​
            console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
        }
    }
    
    // Assign the showData method of the user object to a variable​
    var showDataVar = user.showData;
    showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​
    /*
    This happens because showDataVar () is executed as a global function and use of this inside 
    showDataVar () is bound to the global scope, which is the window object in browsers.
    */
    
    // Bind the showData method to the user object​
    var showDataVar = user.showData.bind (user);
    // Now the we get the value from the user object because the this keyword is bound to the user object​
    showDataVar (); // P. Mickelson 43​
    
  • bind()メソッドの借用を許可する

    // Here we have a cars object that does not have a method to print its data to the console​
    var cars = {
        data:[
           {name:"Honda Accord", age:14},
           {name:"Tesla Model S", age:2}
       ]
    }
    
    // We can borrow the showData () method from the user object we defined in the last example.​
    // Here we bind the user.showData method to the cars object we just created.​
    cars.showData = user.showData.bind (cars);
    cars.showData (); // Honda Accord 14​
    

    この例の問題点の 1 つは、オブジェクトに新しいメソッドを追加することshowDataですcars。車のオブジェクトには既にプロパティまたはメソッド名がある可能性があるため、メソッドを借用するためだけに追加したくない場合がありますshowData。誤って上書きしたくありません。Apply以下のandの説明でわかるように、 orCallのいずれかのメソッドを使用してメソッドを借用するのが最善です。ApplyCall

  • bind()関数をカリー化できるようにする

    Function Curryingは、部分関数適用とも呼ばれ、一部の引数が既に設定されている新しい関数を返す (1 つ以上の引数を受け入れる) 関数の使用です。

    function greet (gender, age, name) {
        // if a male, use Mr., else use Ms.​
        var salutation = gender === "male" ? "Mr. " : "Ms. ";
        if (age > 25) {
            return "Hello, " + salutation + name + ".";
        }else {
            return "Hey, " + name + ".";
        }
     }
    

    この関数bind()をカリー化するために使用できますgreet

    // So we are passing null because we are not using the "this" keyword in our greet function.
    var greetAnAdultMale = greet.bind (null, "male", 45);
    
    greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove."
    
    var greetAYoungster = greet.bind (null, "", 16);
    greetAYoungster ("Alex"); // "Hey, Alex."​
    greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo."
    
  • apply()またはこのcall()を設定するには

    applycallおよびbindメソッドはすべて、メソッドを呼び出すときに this 値を設定するために使用され、JavaScript コードで直接制御と汎用性を使用できるようにするために、わずかに異なる方法で設定します。

    this 値を設定する場合、メソッドapplycallメソッドはほとんど同じですが、メソッドに渡すにはパラメーターを個別にリストする必要がありますが、関数パラメーターを配列apply ()として渡す点が異なります。call ()

    コールバック関数でこれcallを使用またはapply設定する 1 つの例を次に示します。

    // Define an object with some properties and a method​
    // We will later pass the method as a callback function to another function​
    var clientData = {
        id: 094545,
        fullName: "Not Set",
        // setUserName is a method on the clientData object​
        setUserName: function (firstName, lastName)  {
            // this refers to the fullName property in this object​
            this.fullName = firstName + " " + lastName;
        }
    };
    
    function getUserInput (firstName, lastName, callback, callbackObj) {
         // The use of the Apply method below will set the "this" value to callbackObj​
         callback.apply (callbackObj, [firstName, lastName]);
    }
    
    // The clientData object will be used by the Apply method to set the "this" value​
    getUserInput ("Barack", "Obama", clientData.setUserName, clientData);
    // the fullName property on the clientData was correctly set​
    console.log (clientData.fullName); // Barack Obama
    
  • applyまたはで関数を借りるcall

    • 配列メソッドを借りる

      array-likeオブジェクトを作成し、いくつかの配列メソッドを借りて、配列のようなオブジェクトを操作しましょう。

      // An array-like object: note the non-negative integers used as keys​
      var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };
      
       // Make a quick copy and save the results in a real array:
       // First parameter sets the "this" value​
       var newArray = Array.prototype.slice.call (anArrayLikeObj, 0);
       console.log (newArray); // ["Martin", 78, 67, Array[3]]​
      
       // Search for "Martin" in the array-like object​
       console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true​
      

      arguments別の一般的なケースは、次のように配列に変換することです

        // We do not define the function with any parameters, yet we can get all the arguments passed to it​
       function doSomething () {
          var args = Array.prototype.slice.call (arguments);
          console.log (args);
       }
      
       doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"]
      
    • 他の方法を借りる

      var gameController = {
           scores  :[20, 34, 55, 46, 77],
           avgScore:null,
           players :[
                {name:"Tommy", playerID:987, age:23},
                {name:"Pau", playerID:87, age:33}
           ]
       }
       var appController = {
           scores  :[900, 845, 809, 950],
           avgScore:null,
           avg     :function () {
                   var sumOfScores = this.scores.reduce (function (prev, cur, index, array) {
                        return prev + cur;
               });
               this.avgScore = sumOfScores / this.scores.length;
           }
         }
         // Note that we are using the apply () method, so the 2nd argument has to be an array​
         appController.avg.apply (gameController);
         console.log (gameController.avgScore); // 46.4​
         // appController.avgScore is still null; it was not updated, only gameController.avgScore was updated​
         console.log (appController.avgScore); // null​
      
  • 可変アリティ関数のapply()実行に使用

これMath.maxは、可変アリティ関数の一例です。

// We can pass any number of arguments to the Math.max () method​
console.log (Math.max (23, 11, 34, 56)); // 56

しかし、渡す数値の配列がある場合はどうなるMath.maxでしょうか。これはできません:

var allNumbers = [23, 11, 34, 56];
// We cannot pass an array of numbers to the the Math.max method like this​
console.log (Math.max (allNumbers)); // NaN

これは、メソッドが可変個引数関数apply ()の実行に役立つ場所です。上記の代わりに、) を使用して数値の配列を渡す必要があります。apply (

var allNumbers = [23, 11, 34, 56];
// Using the apply () method, we can pass the array of numbers:
console.log (Math.max.apply (null, allNumbers)); // 56
于 2016-04-08T06:45:25.533 に答える
11

Call、Apply、Bind の基本的な違いは次のとおりです。

バインドは、実行コンテキストを画像の後半に配置する場合に使用されます。

元:

var car = { 
  registrationNumber: "007",
  brand: "Mercedes",

  displayDetails: function(ownerName){
    console.log(ownerName + ' this is your car ' + '' + this.registrationNumber + " " + this.brand);
  }
}
car.displayDetails('Nishant'); // **Nishant this is your car 007 Mercedes**

このメソッドを他の変数で使用したいとしましょう

var car1 = car.displayDetails('Nishant');
car1(); // undefined

他の変数で車の参照を使用するには、使用する必要があります

var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes

bind 関数のより広範な使用について話しましょう

var func = function() {
 console.log(this)
}.bind(1);

func();
// Number: 1

なんで?func は番号 1 でバインドされているため、その場合に bind を使用しないと、Global Object を指すことになります。

var func = function() {
 console.log(this)
}.bind({});

func();
// Object

Call、Apply はステートメントを同時に実行したい場合に使用します。

var Name = { 
    work: "SSE",
    age: "25"
}

function displayDetails(ownerName) {
    console.log(ownerName + ", this is your name: " + 'age' + this.age + " " + 'work' + this.work);
}
displayDetails.call(Name, 'Nishant')
// Nishant, this is your name: age25 workSSE

// In apply we pass an array of arguments
displayDetails.apply(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE
于 2019-08-10T06:35:48.017 に答える
7

構文

  • 呼び出し(thisArg、arg1、arg2、...)
  • 適用(thisArg、argsArray)
  • bind (thisArg[, arg1[, arg2[, ...]]])

ここ

  • thisArg はオブジェクトです
  • argArray は配列オブジェクトです
  • arg1、arg2、arg3、... は追加の引数です

function printBye(message1, message2){
    console.log(message1 + " " + this.name + " "+ message2);
}

var par01 = { name:"John" };
var msgArray = ["Bye", "Never come again..."];

printBye.call(par01, "Bye", "Never come again...");
//Bye John Never come again...

printBye.call(par01, msgArray);
//Bye,Never come again... John undefined

//so call() doesn't work with array and better with comma seperated parameters 

//printBye.apply(par01, "Bye", "Never come again...");//Error

printBye.apply(par01, msgArray);
//Bye John Never come again...

var func1 = printBye.bind(par01, "Bye", "Never come again...");
func1();//Bye John Never come again...

var func2 = printBye.bind(par01, msgArray);
func2();//Bye,Never come again... John undefined
//so bind() doesn't work with array and better with comma seperated parameters

于 2017-06-16T14:19:39.603 に答える
3

call() :-- ここでは、配列形式ではなく、関数の引数を個別に渡します

var obj = {name: "Raushan"};

var greeting = function(a,b,c) {
    return "Welcome "+ this.name + " to "+ a + " " + b + " in " + c;
};

console.log(greeting.call(obj, "USA", "INDIA", "ASIA"));

apply() :-- ここでは、関数の引数を配列形式で渡します

var obj = {name: "Raushan"};

var cal = function(a,b,c) {
    return this.name +" you got " + a+b+c;
};

var arr =[1,2,3];  // array format for function arguments
console.log(cal.apply(obj, arr)); 

練る() : -

       var obj = {name: "Raushan"};

       var cal = function(a,b,c) {
            return this.name +" you got " + a+b+c;
       };

       var calc = cal.bind(obj);
       console.log(calc(2,3,4));
于 2019-12-21T20:24:06.663 に答える
2

bind が利用できないと想像してください。次のように簡単に構築できます。

var someFunction=...
var objToBind=....

var bindHelper =  function (someFunction, objToBind) {
    return function() {
        someFunction.apply( objToBind, arguments );
    };  
}

bindHelper(arguments);
于 2016-08-20T10:42:12.703 に答える