Question Quelle est la différence entre un appel et une demande?
Quelle est la différence entre utiliser call
et apply
invoquer une fonction?
var func = function() {
alert('hello!');
};
func.apply();
contre func.call();
Existe-t-il des différences de performance entre les deux méthodes susmentionnées? Quand est-il préférable d'utiliser call
plus de apply
et vice versa?
2737
2017-12-31 19:56
origine
Réponses:
La différence est que apply
vous permet d'invoquer la fonction avec arguments
en tant que tableau; call
nécessite que les paramètres soient listés explicitement. Un mnémonique utile est "UNE pour unerayer et C pour comma. "
Voir la documentation de MDN sur appliquer et appel.
Pseudo syntaxe:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
Il y a aussi, à partir de ES6, la possibilité de spread
le tableau pour une utilisation avec le call
fonction, vous pouvez voir les compatibilités ici.
Exemple de code:
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
3304
2017-12-31 20:00
K. Scott Allen a une belle écriture à ce propos.
Fondamentalement, ils diffèrent sur la façon dont ils traitent les arguments de la fonction.
La méthode apply () est identique à call (), sauf que apply () nécessite un tableau en tant que deuxième paramètre. Le tableau représente les arguments de la méthode cible. "
Alors:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
209
2017-12-31 19:59
Pour répondre à la partie sur le moment d'utiliser chaque fonction, utilisez apply
si vous ne connaissez pas le nombre d'arguments que vous passerez, ou s'ils sont déjà dans un tableau ou un objet semblable à un tableau (comme le arguments
objet pour transmettre vos propres arguments. Utilisation call
sinon, puisqu'il n'y a pas besoin d'envelopper les arguments dans un tableau.
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];
while (...) {
args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments
Quand je ne passe aucun argument (comme votre exemple), je préfère call
depuis que je suis appel la fonction. apply
impliquerait que vous êtes appliquer la fonction aux arguments (inexistants).
Il ne devrait y avoir aucune différence de performance, sauf peut-être si vous utilisez apply
et enveloppez les arguments dans un tableau (par ex. f.apply(thisObject, [a, b, c])
au lieu de f.call(thisObject, a, b, c)
). Je ne l'ai pas testé, donc il pourrait y avoir des différences, mais ce serait très spécifique au navigateur. Il est probable que call
est plus rapide si vous n'avez pas déjà les arguments dans un tableau et apply
est plus rapide si vous le faites.
150
2017-12-31 21:50
Voici un bon mnémonique. UNEutiliser pply UNErays et UNEIl faut toujours un ou deux arguments. Lorsque vous utilisez Ctout ce qu'il faut Count le nombre d'arguments.
102
2017-09-04 13:36
Bien que ce soit un vieux sujet, je voulais juste souligner que .call est légèrement plus rapide que .apply. Je ne peux pas vous dire exactement pourquoi.
Voir jsPerf, http://jsperf.com/test-call-vs-apply/3
[UPDATE!
]
Douglas Crockford mentionne brièvement la différence entre les deux, ce qui peut aider à expliquer la différence de performance ... http://youtu.be/ya4UHuXNygM?t=15m52s
Appliquer prend un tableau d'arguments, tandis que Call prend zéro ou plusieurs paramètres individuels! Ah hah!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
91
2017-11-07 17:36
Suit un extrait de Fermeture: Le Guide définitif de Michael Bolin. Cela peut sembler un peu long, mais il est saturé de beaucoup de perspicacité. De "Annexe B. Concepts JavaScript souvent mal compris":
Quelle this
Fait référence à lorsqu'une fonction est appelée
Lors de l'appel d'une fonction du formulaire foo.bar.baz()
, L'object foo.bar
est appelé le récepteur. Lorsque la fonction est appelée, c'est le récepteur qui est utilisé comme valeur pour this
:
var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
for (var i = 0; i < arguments.length; i++) {
this.value += arguments[i];
}
return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);
S'il n'y a pas de récepteur explicite lorsqu'une fonction est appelée, alors l'objet global devient le récepteur. Comme expliqué dans "goog.global" à la page 47, la fenêtre est l'objet global lorsque JavaScript est exécuté dans un navigateur Web. Cela conduit à un comportement surprenant:
var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN
Même si obj.addValues
et f
se référer à la même fonction, ils se comportent différemment lorsqu'ils sont appelés parce que la valeur du récepteur est différente dans chaque appel. Pour cette raison, lorsque vous appelez une fonction qui fait référence à this
, il est important de s'assurer que this
aura la bonne valeur quand il est appelé. Pour être clair, si this
n'étaient pas référencés dans le corps de la fonction, alors le comportement de f(20)
et obj.addValues(20)
serait le même.
Les fonctions étant des objets de première classe dans JavaScript, elles peuvent avoir leurs propres méthodes. Toutes les fonctions ont les méthodes call()
et apply()
qui permettent de redéfinir le récepteur (c'est-à-dire, l'objet this
fait référence à) lors de l'appel de la fonction. Les signatures de méthode sont les suivantes:
/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;
Notez que la seule différence entre call()
et apply()
est-ce call()
reçoit les paramètres de la fonction en tant qu'arguments individuels, alors que apply()
les reçoit en un seul tableau:
// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);
Les appels suivants sont équivalents, comme f
et obj.addValues
se référer à la même fonction:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
Cependant, puisque ni call()
ni apply()
utilise la valeur de son propre récepteur pour substituer à l'argument récepteur quand il n'est pas spécifié, ce qui suit ne fonctionnera pas:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
La valeur de this
ne peut jamais être null
ou undefined
quand une fonction est appelée. Quand null
ou undefined
est fourni en tant que récepteur call()
ou apply()
, l'objet global est utilisé comme valeur pour le récepteur à la place. Par conséquent, le code précédent a le même effet secondaire indésirable d'ajouter une propriété nommée value
à l'objet global.
Il peut être utile de considérer une fonction comme n'ayant aucune connaissance de la variable à laquelle elle est affectée. Cela contribue à renforcer l'idée que la valeur de ce sera lié lorsque la fonction est appelée plutôt que quand elle est définie.
Fin de l'extrait.
71
2017-12-04 12:41
Il est parfois utile pour un objet d'emprunter la fonction d'un autre objet, ce qui signifie que l'objet emprunteur exécute simplement la fonction prêt comme si elle était la sienne.
Un petit exemple de code:
var friend = {
car: false,
lendCar: function ( canLend ){
this.car = canLend;
}
};
var me = {
car: false,
gotCar: function(){
return this.car === true;
}
};
console.log(me.gotCar()); // false
friend.lendCar.call(me, true);
console.log(me.gotCar()); // true
friend.lendCar.apply(me, [false]);
console.log(me.gotCar()); // false
Ces méthodes sont très utiles pour donner aux objets une fonctionnalité temporaire.
33
2018-02-25 19:31
Un autre exemple avec Call, Apply et Bind.
La différence entre Call et Apply est évidente, mais Lier fonctionne comme ceci:
- Bind renvoie une instance d'une fonction pouvant être exécutée
- Le premier paramètre est 'ce'
- Le deuxième paramètre est un Séparées par des virgules liste d'arguments (comme Appel)
}
function Person(name) {
this.name = name;
}
Person.prototype.getName = function(a,b) {
return this.name + " " + a + " " + b;
}
var reader = new Person('John Smith');
reader.getName = function() {
// Apply and Call executes the function and returns value
// Also notice the different ways of extracting 'getName' prototype
var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
console.log("Apply: " + baseName);
var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy");
console.log("Call: " + baseName);
// Bind returns function which can be invoked
var baseName = Person.prototype.getName.bind(this, "is a", "boy");
console.log("Bind: " + baseName());
}
reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/
23
2018-03-31 07:32
Je voudrais montrer un exemple, où l'argument 'valueForThis' est utilisé:
Array.prototype.push = function(element) {
/*
Native code*, that uses 'this'
this.put(element);
*/
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
**détails: http://es5.github.io/#x15.4.4.7*
21
2017-07-05 10:56
Call () prend des arguments séparés par des virgules, ex:
.call(scope, arg1, arg2, arg3)
et apply () prend un tableau d'arguments, ex:
.apply(scope, [arg1, arg2, arg3])
Voici quelques exemples d'utilisation supplémentaires:
http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
20
2018-01-21 18:11