Appel Javascript() & apply() vs bind()?

je sais déjà que apply et call sont des fonctions similaires qui mettent this (contexte d'une fonction).

la différence réside dans la façon dont nous envoyons les arguments (manuel vs tableau)

Question:

mais quand devrais-je utiliser la méthode 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

641
demandé sur Sun 2013-03-17 01:40:08

16 réponses

utiliser .bind() quand vous voulez que cette fonction soit appelée plus tard avec un certain contexte, utile dans les événements. Utilisez .call() ou .apply() lorsque vous voulez invoquer la fonction immédiatement et modifier le contexte.

l'Appel/s'appliquent appelez la fonction immédiatement, alors que les bind retourne une fonction qui, lorsqu'elles sont exécutées, ont le bon cadre pour l'appel de la fonction d'origine. De cette façon, vous pouvez maintenir le contexte dans les callbacks async et événement.

je le fais beaucoup de choses:

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.
};

Je l'utilise largement dans Node.js pour les callbacks async pour lesquels je veux passer une méthode member, mais je veux quand même que le contexte soit l'instance qui a démarré l'action async.

une mise en œuvre simple et naïve de bind serait comme:

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

il y a plus (comme passer d'autres args), mais vous pouvez lire plus à ce sujet et voir la mise en œuvre réelle sur le MDN .

Espérons que cette aide.

672
répondu Chad 2017-06-14 20:03:26

ils attachent tous ce dans la fonction (ou l'objet) et la différence est dans la fonction invocation (voir ci-dessous).

appel attache ce en fonction et exécute la fonction immédiatement:

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"

lier attache ce en fonction et il doit être invoqué séparément comme ceci:

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"

ou comme ceci:

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

appliquer est similaire à appel sauf qu'il prend un tableau comme objet plutôt que d'énumérer les arguments un à un:

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"                                     
376
répondu CuriousSuperhero 2017-06-30 10:03:50

réponse sous la forme la plus simple

  • Call invoque la fonction et vous permet de passer dans les arguments un par un.
  • Appliquer appelle la fonction et vous permet de passer en arguments comme un tableau.
  • Lier renvoie une nouvelle fonction, vous permettant de passer dans un ce tableau et n'importe quel nombre d'arguments.

Appliquer vs Call et Lier des Exemples

Appel

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say(greeting) {
    console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}

say.call(person1, 'Hello'); // Hello Jon Kuperman
say.call(person2, 'Hello'); // Hello Kelly King

appliquer

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say(greeting) {
    console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}

say.apply(person1, ['Hello']); // Hello Jon Kuperman
say.apply(person2, ['Hello']); // Hello Kelly King

Lier

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say() {
    console.log('Hello ' + this.firstName + ' ' + this.lastName);
}

var sayHelloJon = say.bind(person1);
var sayHelloKelly = say.bind(person2);

sayHelloJon(); // Hello Jon Kuperman
sayHelloKelly(); // Hello Kelly King

Quand Utiliser Chaque

sont assez interchangeables. Il suffit de décider s'il est plus facile d'envoyer un tableau ou une liste d'arguments séparés par des virgules.

je me souviens toujours lequel est celui qui, en se rappelant que L'appel est pour la virgule (liste séparée) et S'applique est pour le tableau.

Bind est un peu différent. Il renvoie une nouvelle fonction. Appelez et appliquez exécutez la fonction courante immédiatement.

Bind est grand pour beaucoup de choses. Nous pouvons l'utiliser pour curry de fonctions comme dans l'exemple ci-dessus. Nous pouvons prendre une simple fonction hello et la transformer en un helloJon ou helloKelly. Nous pouvons également l'utiliser pour des événements comme onClick où nous ne savons pas quand ils vont être licenciés, mais nous savons ce contexte, nous voulons qu'ils ont.

Referance: codeplanet.io

74
répondu Amit Shah 2017-10-12 02:47:02

Il permet de définir la valeur de this indépendamment de la façon dont la fonction est appelée. Ceci est très utile pour travailler avec les callbacks:

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

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

pour obtenir le même résultat avec call ressemblerait à ceci:

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

  var obj = {
     message : "hello"
  };
  setTimeout(function(){sayHello.call(obj)}, 1000);
51
répondu jantimon 2013-03-16 21:50:20

supposons que nous avons multiplication fonction

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

permet de créer des fonctions standard en utilisant bind

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

Maintenant multiby2(b) est égale à la multiplication(2,b);

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

Que faire si je passe les deux paramètres dans bind

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

Maintenant getSixAlways() est égale à la multiplication(3,2);

getSixAlways();//6

même paramètre de passage renvoie 6; getSixAlways(12); //6

var magicMultiplication = multiplication.bind(this);

cela crée une nouvelle fonction de multiplication et l'assigne à magicMultiplication.

Oh non, nous cache la multiplication des fonctionnalités dans magicMultiplication.

appel magicMultiplication renvoie un blanc function b()

sur l'exécution, il fonctionne très bien magicMultiplication(6,5); //30

pourquoi pas call et de les appliquer?

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

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

en termes simples, bind crée la fonction, call et apply exécute la fonction tandis que apply attend les paramètres dans le tableau

40
répondu tk120404 2015-06-12 09:16:13

les deux Function.prototype.call() et Function.prototype.apply() appeler une fonction avec une valeur this donnée, et retourner la valeur de retour de cette fonction.

Function.prototype.bind() , d'un autre côté, crée une nouvelle fonction avec une valeur this donnée, et retourne cette fonction sans l'exécuter.

donc, prenons une fonction qui ressemble à ceci:

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

Maintenant, prenons un objet qui ressemble à ceci:

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

nous pouvons lier notre fonction à notre objet comme ceci:

Obj.log = logProp.bind(Obj);

maintenant, nous pouvons exécuter Obj.log n'importe où dans notre code:

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

où il devient vraiment intéressant, est quand vous non seulement liez une valeur pour this , mais aussi pour son argument prop :

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

nous pouvons maintenant faire ceci:

Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
28
répondu John Slegers 2016-01-18 03:59:16

voici un bon article pour illustrer la différence entre bind() , apply() et call() , résumez-le comme suit.

  • bind() permet de définir facilement quel objet spécifique sera lié à ce lorsqu'une fonction ou une méthode est invoquée.

    // 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() nous permettent d'emprunter des méthodes

    // 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​
    

    un problème avec cet exemple est que nous ajoutons une nouvelle méthode showData sur l'objet cars et nous pourrions ne pas vouloir faire cela juste pour emprunter une méthode parce que l'objet cars pourrait déjà avoir une propriété ou le nom de méthode showData . Nous ne voulons pas de les effacer accidentellement. Comme nous le verrons dans notre discussion de Apply et Call ci-dessous, il est préférable d'emprunter une méthode utilisant soit le Apply ou Call méthode.

  • bind() nous permettre de curry une fonction

    fonction Currying , également connu sous le nom de application partielle de fonction , est l'utilisation d'un fonction (qui accepte un ou plusieurs arguments) qui renvoie une nouvelle fonction avec certains des arguments déjà définis.

    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 + ".";
        }
     }
    

    nous pouvons utiliser bind() greet fonction

    // 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() ou call() pour définir ce valeur

    les méthodes apply , call , et bind sont toutes utilisées pour définir cette valeur lors de l'invocation d'une méthode, et ils le font dans légèrement différentes façons d'utiliser le contrôle direct et la polyvalence dans notre code JavaScript.

    le apply et Les méthodes call sont presque identiques lorsque vous définissez cette valeur , sauf que vous passez les paramètres de fonction à apply () comme un tableau , alors que vous devez énumérer les paramètres individuellement pour les passer à la méthode call () .

    voici un exemple pour utiliser call ou apply pour définir ce dans la fonction de rappel.

    // 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
    
  • fonctions D'emprunt avec apply ou call

    • Emprunter les méthodes de Tableau

      créons un objet array-like et empruntons quelques méthodes array pour opérer sur l'objet de type our array.

      // 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​
      

      un autre cas courant est celui de convertir arguments en tableau comme suit

        // 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"]
      
    • Emprunter d'autres les méthodes de

      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​
      
  • Utiliser apply() pour exécuter variable-arité fonction

le Math.max est un exemple de fonction d'arité variable,

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

mais si nous avions un tableau de nombres à passer à Math.max ? Nous ne pouvons pas faire cela:

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

C'est ici que la méthode apply () nous aide à exécuter fonctions variadiques . Au lieu de ce qui précède, nous devons passer le tableau des nombres en utilisant apply ( ) ainsi:

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
15
répondu zangw 2016-04-08 06:45:25

lier : Il lie la fonction avec la valeur et le contexte, mais il n'exécute la fonction. Pour exécuter la fonction, vous devez appeler la fonction.

appel : Il exécute la fonction avec le contexte et les paramètres.

apply : il exécute la fonction avec le contexte fourni et paramètre en tant que tableau .

11
répondu Siddhartha 2017-11-22 17:31:46

appel exécute la fonction immédiatement:

func.call(context, arguments);
func.apply(context, [argument1,argument2,..]);

lier ne pas exécuter la fonction immédiatement, mais renvoie enveloppé appliquer de la fonction (pour exécution ultérieure):

function bind(func, context) {
    return function() {
        return func.apply(context, arguments);
    };
}
6
répondu Eldiyar Talantbek 2017-02-07 19:34:54
  • Appel appelle la fonction et vous permet de passer en arguments un par un.
  • Apply invoque la fonction et vous permet de passer dans les arguments comme un tableau.
  • Lier retourne une nouvelle fonction, vous permettant de passer dans ce tableau et un nombre quelconque d'arguments.
5
répondu Khalid Azam 2016-12-31 22:01:29

Appel s'appliquent et se lient. et comment ils sont différents.

permet d'apprendre à appeler et à appliquer en utilisant n'importe quelle terminologie quotidienne.

vous avez trois automobiles your_scooter , your_car and your_jet qui commencent avec le même mécanisme (méthode). Nous avons créé un objet automobile avec une méthode push_button_engineStart .

var your_scooter, your_car, your_jet;
var automobile = {
        push_button_engineStart: function (runtime){
        console.log(this.name + "'s" + ' engine_started, buckle up for the ride for ' + runtime + " minutes");
    }
}

permet de comprendre quand l'appel et l'application sont utilisés. Laisse supposer que vous êtes ingénieur et vous avez your_scooter , your_car et your_jet qui n'est pas venu avec un push_button_engine_start et vous souhaitez utiliser un tiers push_button_engineStart .

si vous exécutez les lignes de code suivantes, elles donneront une erreur. Pourquoi?

//your_scooter.push_button_engineStart();
//your_car.push_button_engineStart();
//your_jet.push_button_engineStart();


automobile.push_button_engineStart.apply(your_scooter,[20]);
automobile.push_button_engineStart.call(your_jet,10);
automobile.push_button_engineStart.call(your_car,40);

ainsi, l'exemple ci-dessus donne avec succès à votre_scooter, votre_car, votre_jet une fonctionnalité de l'objet automobile.

Let's enfoncent de plus en plus Ici, nous allons diviser le au-dessus de la ligne de code. automobile.push_button_engineStart nous aide à obtenir la méthode utilisée.

ensuite, nous utilisons appliquer ou appeler en utilisant la notation de point. automobile.push_button_engineStart.apply()

maintenant appliquer et appeler accepter deux paramètres.

  1. contexte
  2. arguments

donc ici nous définissons le contexte dans la ligne finale du code.

automobile.push_button_engineStart.apply(your_scooter,[20])

différence entre call et apply est juste que apply accepte les paramètres sous la forme d'un tableau alors que call peut simplement accepter une liste d'arguments séparée par une virgule.

qu'est-ce que la fonction JS Bind?

une fonction bind est fondamentalement une fonction qui lie le contexte de quelque chose et le stocke ensuite dans une variable pour exécution à un stade ultérieur.

faisons notre exemple précédent encore mieux. Plus tôt, nous avons utilisé une méthode appartenant à l'objet de l'automobile et utilisé pour équiper your_car, your_jet and your_scooter . Imaginons maintenant que nous voulions donner un push_button_engineStart séparé pour démarrer nos automobiles individuellement à n'importe quelle étape ultérieure de l'exécution que nous souhaitons.

var scooty_engineStart = automobile.push_button_engineStart.bind(your_scooter);
var car_engineStart = automobile.push_button_engineStart.bind(your_car);
var jet_engineStart = automobile.push_button_engineStart.bind(your_jet);


setTimeout(scooty_engineStart,5000,30);
setTimeout(car_engineStart,10000,40);
setTimeout(jet_engineStart,15000,5);

toujours pas satisfait?

soyons clairs comme larme. Le temps d'expérimenter. Que nous réfractassions pour appeler et appliquer l'application de fonction et essayer de stocker la valeur de la fonction comme une référence.

l'expérience ci-dessous échoue parce que l'appel et l'application sont invoqués immédiatement, Donc, nous n'arrivons jamais au stade de stocker une référence dans une variable qui est où la fonction bind vole le spectacle

var test_function = automobile.push_button_engineStart.apply(your_scooter);

4
répondu Sagar Munjal 2017-03-28 06:26:54
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
2
répondu Shiljo 2017-06-16 14:29:05

Imaginez, bind n'est pas disponible. vous pouvez facilement construire comme suit :

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

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

bindHelper(arguments);
0
répondu Philippe Oceangermanique 2016-08-20 10:42:12
    function sayHello() {
            //alert(this.message);
            return this.message;
    }
    var obj = {
            message: "Hello"
    };

    function x(country) {
            var z = sayHello.bind(obj);
            setTimeout(y = function(w) {
//'this' reference not lost
                    return z() + ' ' + country + ' ' + w;
            }, 1000);
            return y;
    }
    var t = x('India')('World');
    document.getElementById("demo").innerHTML = t;
0
répondu pandhari 2017-12-15 09:49:49

je pense que les mêmes endroits d'entre eux sont: tous peuvent changer la cette valeur d'une fonction.Les différences sont les suivantes: la fonction bind renverra une nouvelle fonction en conséquence; les méthodes call et apply exécuteront la fonction immédiatement, mais apply peut accepter un tableau comme params,et il parsera le tableau séparé.Et aussi, la fonction de liaison peut être Nourrissage.

-1
répondu Xin Tao 2016-04-15 09:36:38

lier fonction doit être utilisée lorsque l'on veut attribuer une fonction à un contexte particulier, par exemple.

var demo = {
           getValue : function(){ 
             console.log('demo object get value       function') 
            }
           setValue : function(){  
              setTimeout(this.getValue.bind(this),1000)           
           }
 }

dans l'exemple ci-dessus, si nous appelons de démonstration.setValue() de la fonction et de passer cette.la fonction getValue directement puis elle n'appelle pas demo.la fonction setValue directement parce que ceci dans setTimeout se réfère à l'objet window, nous devons donc passer le contexte de l'objet demo à celui-ci.fonction getValue utilisant bind. cela signifie que nous passons seulement la fonction avec le contexte de l'objet de démonstration pas actully l'appel de la fonction.

J'espère que vous comprenez .

pour de plus amples informations, veuillez consulter javascript fonction de liaison savoir dans le détail

-3
répondu user7339156 2016-12-25 06:52:21