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' thisune fonction sera la valeur que vous désirez.
Un exemple courant est setTimeoutcelui qui a lieu à l'intérieur d'un clickgestionnaire.
Prends ça:
$('#myElement').click(function() {
// In this function, "this" is our DOM element.
$(this).addClass('aNewClass');
});
L'intention est assez simple. Quand myElementest cliqué, il devrait obtenir la classe aNewClass. À l'intérieur du gestionnaire thisrepré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 setTimeoutpour l'accomplir, mais le problème est que quelle que soit la fonction que nous attribuons setTimeout, la valeur de l' thisintérieur de cette fonction sera windowau 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 thisest 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 thiscontexte approprié .
$.proxy(function () {...}, this)plutôt que (function() {...}).call(this)? Y a-t-il une différence?
.callvous appelez la fonction immédiatement. Avec $.proxy, c'est comme Function.prototype.bindlà où il renvoie une nouvelle fonction. Cette nouvelle fonction a la thisvaleur liée de façon permanente, de sorte que lorsqu'elle est transmise à setTimeoutet setTimeoutappelle la fonction plus tard, elle aura toujours la thisvaleur 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 à foobarl'objet que nous avons passé:
function foobar() {
this.test // === 5
}
C'est exactement ce que jQuery.proxy()fait. Il prend un functionand 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>