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 dois-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));
Utilisez .bind()
lorsque vous souhaitez que cette fonction soit appelée ultérieurement avec un certain contexte, utile dans les événements. Utilisez .call()
ou .apply()
lorsque vous souhaitez appeler la fonction immédiatement et modifier le contexte.
Call/apply appelle immédiatement la fonction, alors que bind
renvoie une fonction qui, lorsqu'elle sera exécutée ultérieurement, aura le contexte correct défini pour appeler la fonction d'origine. De cette façon, vous pouvez conserver le contexte dans les rappels 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 abondamment dans Node.js pour les rappels asynchrones pour lesquels je souhaite transmettre une méthode de membre, mais je veux tout de 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 la suivante:
Function.prototype.bind = function(ctx) {
var fn = this;
return function() {
fn.apply(ctx, arguments);
};
};
Il y a plus que cela (comme passer d'autres arguments), mais vous pouvez en lire plus à ce sujet et voir la vraie mise en œuvre sur le MDN .
J'espère que cela t'aides.
Ils attachent tousthisà une fonction (ou à un objet) et la différence réside dans l'appel de la fonction (voir ci-dessous).
call attachesthisinto function et l'exécute 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"
bind attachesthisdans la fonction et 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"
apply est similaire à call sauf qu'il prend un objet de type tableau au lieu de lister les arguments un par 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"
Répondre en forme SIMPLEST
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
Appeler et appliquer 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 rappelle toujours lequel est lequel en se rappelant que Call est pour virgule (liste séparée) et Apply est pour Array.
Bind est un peu différent. Il retourne une nouvelle fonction. Call et Apply exécutent immédiatement la fonction en cours.
Bind est idéal pour beaucoup de choses. Nous pouvons l'utiliser pour curry des fonctions 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 licenciés, mais nous savons quel contexte nous voulons qu’ils aient.
Référence: codeplanet.io
Il permet de définir la valeur pour this
indépendamment 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 obtenir le même résultat avec call
, cela ressemble à ceci:
function sayHello(){
alert(this.message);
}
var obj = {
message : "hello"
};
setTimeout(function(){sayHello.call(obj)}, 1000);
Les deux Function.prototype.call()
et Function.prototype.apply()
appellent une fonction avec une valeur this
donnée et renvoient la valeur de retour de cette fonction.
Function.prototype.bind()
, d'autre part, crée une nouvelle fonction avec une valeur this
donnée 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 exécuter Obj.log
n'importe où dans notre code:
Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10
Cela devient vraiment intéressant lorsque vous ne liez pas seulement 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
bind : Il lie la fonction avec la valeur fournie et le contexte mais n'exécute pas la fonction. Pour exécuter une fonction, vous devez l'appeler.
call : Il exécute la fonction avec le contexte et le paramètre fournis.
apply : Il exécute la fonction avec le contexte fourni et le paramètre en tant que tableau .
Voici un bon article pour illustrer la différence entre bind()
, apply()
et call()
, résumez-le comme suit.
bind()
nous permet de définir facilement quel objet spécifique sera lié à this quand une fonction ou une méthode est appelé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 permet 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
à l’objet cars
et à Nous ne voudrions peut-être pas le faire uniquement pour emprunter une méthode car l’objet cars pourrait déjà avoir une propriété ou un nom de méthode showData
.Nous ne voulons pas écraser accidentellement. Comme nous le verrons dans notre discussion de Apply
et Call
ci-dessous, Il est préférable d'emprunter une méthode à l'aide de la méthode Apply
ou Call
.
bind()
nous permet de curry une fonction
La fonction currying , également appelée application de fonction partielle, est l'utilisation d'une fonction (Qui accepte un ou plusieurs arguments) qui renvoie une nouvelle fonction avec certains 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()
pour curry cette fonction 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()
ou call()
pour définir this value
Les méthodes apply
, call
et bind
sont toutes utilisées pour définir cette valeur lors de l'appel d'une méthode. Elles le font de manière légèrement différente pour permettre l'utilisation du contrôle direct et de la polyvalence de notre code JavaScript.
Les méthodes apply
et call
sont presque identiques lorsque vous définissez la valeur this sauf que vous transmettez les paramètres de la fonction à apply ()
sous la forme un tableau, tandis que vous devez répertorier les paramètres individuellement la méthode call ()
.
Voici un exemple d'utilisation de call
ou apply
pour définir this 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
Méthodes Emprunter un tableau
Créons un objet array-like
et empruntons des méthodes de tableau pour opérer sur notre objet semblable à un 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 qui convertit 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 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
Utilisez apply()
pour exécuter la fonction variable-arity
Le Math.max
est un exemple de fonction à 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 se passe-t-il si nous avons un tableau de nombres à transmettre à 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 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 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
appelle/applique exécute la fonction immédiatement:
func.call(context, arguments);
func.apply(context, [argument1,argument2,..]);
bind n'exécute pas la fonction immédiatement, mais retourne la fonction apply enveloppée (pour une exécution ultérieure):
function bind(func, context) {
return function() {
return func.apply(context, arguments);
};
}
La différence fondamentale entre Call, Apply et Bind est la suivante:
Lier sera utilisé si vous voulez que votre contexte d’exécution vienne plus tard dans l’image.
Ex:
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**
Disons que je veux utiliser cette méthode dans une autre variable
var car1 = car.displayDetails('Nishant');
car1(); // undefined
Pour utiliser la référence de voiture dans une autre variable, vous devez utiliser
var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes
Parlons de l'utilisation plus étendue de la fonction bind
var func = function() {
console.log(this)
}.bind(1);
func();
// Number: 1
Pourquoi? Parce que maintenant func est lié au numéro 1, si nous n'utilisons pas de lien dans ce cas, il pointe sur un objet global.
var func = function() {
console.log(this)
}.bind({});
func();
// Object
Appelez, appliquez sont utilisés lorsque vous voulez exécuter l'instruction en même temps.
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 the array
displayDetails.call(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE
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
Call: call appelle la fonction et vous permet de passer des arguments un à un.
Apply: Apply appelle la fonction et vous permet de transmettre des arguments sous forme de tableau.
Bind: Bind renvoie une nouvelle fonction, vous permettant de passer un tableau this et un nombre quelconque d'arguments.
var person1 = {firstName: 'Raju', lastName: 'king'};
var person2 = {firstName: 'chandu', lastName: 'shekar'};
function greet(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
function greet2(greeting) {
console.log( 'Hello ' + this.firstName + ' ' + this.lastName);
}
greet.call(person1, 'Hello'); // Hello Raju king
greet.call(person2, 'Hello'); // Hello chandu shekar
greet.apply(person1, ['Hello']); // Hello Raju king
greet.apply(person2, ['Hello']); // Hello chandu shekar
var greetRaju = greet2.bind(person1);
var greetChandu = greet2.bind(person2);
greetRaju(); // Hello Raju king
greetChandu(); // Hello chandu shekar
Imaginez, bind n'est pas disponible. vous pouvez facilement le construire comme suit:
var someFunction=...
var objToBind=....
var bindHelper = function (someFunction, objToBind) {
return function() {
someFunction.apply( objToBind, arguments );
};
}
bindHelper(arguments);
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;