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


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

La différence est avec la façon dont nous envoyons les arguments (manuel vs tableau)

Question:

Mais quand devrais-je utiliser le bind() méthode ?

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


619
2018-03-16 21:40


origine


Réponses:


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

Appeler / appliquer appelle la fonction immédiatement, tandis que bind renvoie une fonction qui, lorsqu'elle sera exécutée plus tard, aura le contexte approprié pour appeler la fonction d'origine. De cette façon, vous pouvez maintenir le contexte dans les callbacks et les événements asynchrones.

Je le fais beaucoup:

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 beaucoup dans Node.js pour les callbacks asynchrones pour lesquels je veux passer une méthode membre, mais je veux quand même que le contexte soit l'instance qui a démarré l'action asynchrone.

Une implémentation 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 arguments), mais vous pouvez en lire plus à ce sujet et voir la vraie implémentation sur le MDN.

J'espère que cela t'aides.


646
2018-03-16 21:44



Ils attachent tous ce dans la fonction (ou l'objet) et la différence est dans l'invocation de la fonction (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 objet de type tableau au lieu d'énumérer les arguments un à la fois:

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"                                     

365
2017-08-10 14:50



Répondez au format SIMPLEST

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

Appliquez vs Appelez vs Bind 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 chacun

Appelez et appliquez sont assez interchangeables. Décidez simplement s'il est plus facile d'envoyer un tableau ou une liste d'arguments séparés par des virgules.

Je me rappelle toujours lequel est en se souvenant que l'appel est pour la virgule (liste séparée) et que Apply est pour Array.

La liaison est un peu différente. Il retourne une nouvelle fonction. Call et Apply exécutent la fonction en cours immédiatement.

La liaison est idéale pour beaucoup de choses. Nous pouvons l'utiliser pour les fonctions curry comme dans l'exemple ci-dessus. Nous pouvons prendre une simple fonction Hello et la transformer en HelloJon ou HelloKelly. Nous pouvons également l'utiliser pour des événements comme onClick où nous ne savons pas quand ils seront renvoyés mais nous savons quel contexte nous voulons qu'ils aient.

Référence: codeplanet.io


56
2017-10-12 02:47



Cela permet de définir la valeur de this indépendant de la façon dont la fonction est appelée. Ceci est très utile lorsque vous travaillez avec des rappels:

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

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

Pour atteindre le même résultat avec callressemblerait à ceci:

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

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

51
2018-03-16 21:45



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 égal à 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 égal à la multiplication (3,2);

getSixAlways();//6

même en passant le paramètre retourne 6;     getSixAlways(12); //6 

var magicMultiplication = multiplication.bind(this);

Cela crée une nouvelle fonction de multiplication et l'affecte à magicMultiplication.

Oh non, nous cachons la fonctionnalité de multiplication dans magicMultiplication.

appel magicMultiplication renvoie un blanc function b()

lors de l'exécution, cela fonctionne bien magicMultiplication(6,5); //30

Que diriez-vous appeler et 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 alors que apply attend les paramètres dans le tableau


40
2018-06-10 18:04



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

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

Alors, 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 courir Obj.log n'importe où dans notre code:

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

Là où ça devient vraiment intéressant, c'est quand vous liez non seulement une valeur pour thismais 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

25
2018-01-18 03:59



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

  • bind() nous 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 permettre 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 le cars objet et nous pourrions ne pas vouloir faire cela juste pour emprunter une méthode car l'objet cars pourrait déjà avoir un nom de propriété ou de méthode showData. Nous ne voulons pas l'écraser accidentellement. Comme nous le verrons dans notre discussion de Apply et Call au dessous de, il est préférable d'emprunter une méthode en utilisant soit le Apply ou Call méthode.

  • bind() nous permettre d'organiser une fonction

    Fonction Currying, aussi connu sous le nom application de fonction partielle, est l'utilisation d'un function (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 + ".";
        }
     }
    

    On peut utiliser bind() pour le curry 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() mettre en place ce valeur

    le apply, call, et bind méthodes sont tous utilisés pour définir cette valeur lors de l'appel d'une méthode, et ils le font dans un petit différentes façons d'utiliser le contrôle direct et la polyvalence dans notre code JavaScript.

    le apply et call méthodes sont presque identiques lors de la définition de cette valeur sauf que vous passez les paramètres de la fonction à apply () comme un tableau, alors que vous devez Lister les paramètres individuellement pour les transmettre à call () méthode.

    Voici un exemple à utiliser call ou apply mettre en place 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
    
  • Emprunter des fonctions avec apply ou call

    • Emprunter les méthodes Array

      Créons un array-like objet et emprunter des méthodes de tableau pour fonctionner sur l'objet de notre tableau.

      // 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 au 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 méthodes

      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​
      
  • Utilisation apply() éxé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 que faire si nous avons un tableau de nombres à passer à Math.max? Nous ne pouvons pas faire ceci:

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 là que le apply () méthode nous aide à exécuter fonctions variadiques. Au lieu de ce qui précède, nous devons passer le tableau de 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

13
2018-04-08 06:45



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

appel: Il exécute la fonction avec le contexte et le paramètre fournis.

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


7
2017-11-22 17:31



appeler / appliquer exécute la fonction immédiatement:

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

lier n'exécute pas la fonction immédiatement, mais retourne emballé appliquer fonction (pour exécution ultérieure):

function bind(func, context) {
    return function() {
        return func.apply(context, arguments);
    };
}

5
2018-02-07 19:34