D'après la documentation, je comprends que .proxy()
cela changerait la portée de la fonction passée en argument. Quelqu'un pourrait-il mieux m'expliquer cela? Pourquoi devrions-nous faire cela?
D'après la documentation, je comprends que .proxy()
cela changerait la portée de la fonction passée en argument. Quelqu'un pourrait-il mieux m'expliquer cela? Pourquoi devrions-nous faire cela?
Réponses:
En fin de compte, il garantit que la valeur d' this
une fonction sera la valeur que vous désirez.
Un exemple courant est setTimeout
celui qui a lieu à l'intérieur d'un click
gestionnaire.
Prends ça:
$('#myElement').click(function() {
// In this function, "this" is our DOM element.
$(this).addClass('aNewClass');
});
L'intention est assez simple. Quand myElement
est cliqué, il devrait obtenir la classe aNewClass
. À l'intérieur du gestionnaire this
représente l'élément sur lequel l'utilisateur a cliqué.
Mais que faire si nous voulions un court délai avant d'ajouter la classe? Nous pourrions utiliser a setTimeout
pour l'accomplir, mais le problème est que quelle que soit la fonction que nous attribuons setTimeout
, la valeur de l' this
intérieur de cette fonction sera window
au lieu de notre élément.
$('#myElement').click(function() {
setTimeout(function() {
// Problem! In this function "this" is not our element!
$(this).addClass('aNewClass');
}, 1000);
});
Donc, ce que nous pouvons faire à la place, c'est d'appeler $.proxy()
, de lui envoyer la fonction et la valeur que nous voulons attribuer this
, et cela retournera une fonction qui conservera cette valeur.
$('#myElement').click(function() {
// ------------------v--------give $.proxy our function,
setTimeout($.proxy(function() {
$(this).addClass('aNewClass'); // Now "this" is again our element
}, this), 1000);
// ---^--------------and tell it that we want our DOM element to be the
// value of "this" in the function
});
Donc, après avoir donné $.proxy()
la fonction et la valeur que nous voulons this
, elle a renvoyé une fonction qui garantira qu'elle this
est correctement définie.
Comment ça marche? Il renvoie simplement une fonction anonyme qui appelle notre fonction à l'aide de la .apply()
méthode, ce qui lui permet de définir explicitement la valeur de this
.
Un aperçu simplifié de la fonction renvoyée peut ressembler à ceci:
function() {
// v--------func is the function we gave to $.proxy
func.apply( ctx );
// ----------^------ ctx is the value we wanted for "this" (our DOM element)
}
Donc, cette fonction anonyme est donnée à setTimeout
, et tout ce qu'elle fait est d'exécuter notre fonction d'origine avec le this
contexte approprié .
$.proxy(function () {...}, this)
plutôt que (function() {...}).call(this)
? Y a-t-il une différence?
.call
vous appelez la fonction immédiatement. Avec $.proxy
, c'est comme Function.prototype.bind
là où il renvoie une nouvelle fonction. Cette nouvelle fonction a la this
valeur liée de façon permanente, de sorte que lorsqu'elle est transmise à setTimeout
et setTimeout
appelle la fonction plus tard, elle aura toujours la this
valeur correcte .
Sans entrer dans les détails (ce qui serait nécessaire car il s'agit de Contexte dans ECMAScript, la variable de contexte this etc.)
Il existe trois types différents de «contextes» dans ECMA- / Javascript:
Chaque code est exécuté dans son contexte d'exécution . Il y en a un contexte global et il peut y avoir de nombreuses instances de contextes de fonction (et d'évaluation). Maintenant la partie intéressante:
Chaque appel d'une fonction entre dans le contexte d'exécution de la fonction. Un contexte d'exécution d'une fonction ressemble à ceci:
La
portée de l' objet d'activation Chaîne
cette valeur
Donc, cette valeur est un objet spécial qui est lié au contexte d'exécution. Il existe deux fonctions dans ECMA- / Javascript qui peuvent changer la valeur this dans un contexte d'exécution de fonction:
.call()
.apply()
Si nous avons une fonction, foobar()
nous pouvons changer la valeur this en appelant:
foobar.call({test: 5});
Maintenant, nous pouvons accéder à foobar
l'objet que nous avons passé:
function foobar() {
this.test // === 5
}
C'est exactement ce que jQuery.proxy()
fait. Il prend un function
and context
(qui n'est rien d'autre qu'un objet) et lie la fonction en invoquant .call()
ou .apply()
et renvoie cette nouvelle fonction.
Le même objectif peut être atteint en utilisant une fonction auto- exécutable "Expression de fonction immédiatement appelée, abrégée: IIFE" :
$('#myElement').click(function() {
(function(el){
setTimeout(function() {
// Problem! In this function "this" is not our element!
el.addClass('colorme');
}, 1000);
})($(this)); // self executing function
});
.colorme{
color:red;
font-size:20px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<div id="myElement">Click me</div>
</body>
</html>