De los documentos , entiendo que .proxy()
cambiaría el alcance de la función pasada como argumento. ¿Podría alguien explicarme esto mejor? ¿Por qué deberíamos hacer ésto?
De los documentos , entiendo que .proxy()
cambiaría el alcance de la función pasada como argumento. ¿Podría alguien explicarme esto mejor? ¿Por qué deberíamos hacer ésto?
Respuestas:
Lo que finalmente hace es garantizar que el valor de this
una función sea el valor que desee.
Un ejemplo común es el setTimeout
que tiene lugar dentro de un click
controlador.
Toma esto:
$('#myElement').click(function() {
// In this function, "this" is our DOM element.
$(this).addClass('aNewClass');
});
La intención es lo suficientemente simple. Cuando myElement
se hace clic, debería obtener la clase aNewClass
. Dentro del controlador this
representa el elemento en el que se hizo clic.
Pero, ¿y si quisiéramos un pequeño retraso antes de agregar la clase? Podríamos usar a setTimeout
para lograrlo, pero el problema es que cualquiera que sea la función que le demos setTimeout
, el valor de this
dentro de esa función será en window
lugar de nuestro elemento.
$('#myElement').click(function() {
setTimeout(function() {
// Problem! In this function "this" is not our element!
$(this).addClass('aNewClass');
}, 1000);
});
Entonces, lo que podemos hacer es llamar $.proxy()
, enviarle la función y el valor que queremos asignar this
, y devolverá una función que retendrá ese valor.
$('#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
});
Entonces, después de que le dimos $.proxy()
la función y el valor que deseamos this
, devolvió una función que garantizará que this
se establezca correctamente.
Como lo hace Simplemente devuelve una función anónima que llama a nuestra función utilizando el .apply()
método, que le permite establecer explícitamente el valor de this
.
Un aspecto simplificado de la función que se devuelve puede verse así:
function() {
// v--------func is the function we gave to $.proxy
func.apply( ctx );
// ----------^------ ctx is the value we wanted for "this" (our DOM element)
}
Por lo tanto, se le asigna esta función anónima setTimeout
y todo lo que hace es ejecutar nuestra función original con el this
contexto adecuado .
$.proxy(function () {...}, this)
lugar de (function() {...}).call(this)
? ¿Hay una diferencia?
.call
usted está llamando a la función de inmediato. Con $.proxy
, es como Function.prototype.bind
donde devuelve una nueva función. Esa nueva función tiene el this
valor enlazado permanentemente, de modo que cuando se pasa setTimeout
y setTimeout
llama a la función más tarde, seguirá teniendo el this
valor correcto .
Sin entrar en mayor detalle (lo cual sería necesario porque se trata de Contexto en ECMAScript, la variable de contexto de este, etc.)
Hay tres tipos diferentes de "Contextos" en ECMA- / Javascript:
Cada código se ejecuta en su contexto de ejecución . Hay un contexto global y puede haber muchas instancias de contextos de función (y evaluación). Ahora la parte interesante:
Cada llamada de una función ingresa al contexto de ejecución de la función. El contexto de ejecución de una función se ve así:
El objeto de activación
Alcance encadena
este valor
Entonces, este valor es un objeto especial que está relacionado con el contexto de ejecución. Hay dos funciones en ECMA- / Javascript que pueden cambiar este valor en un contexto de ejecución de función:
.call()
.apply()
Si tenemos una función foobar()
, podemos cambiar este valor llamando a:
foobar.call({test: 5});
Ahora podríamos acceder en foobar
el objeto que pasamos:
function foobar() {
this.test // === 5
}
Esto es exactamente lo que jQuery.proxy()
hace. Toma un function
y context
(que no es más que un objeto) y vincula la función invocando .call()
o .apply()
y devuelve esa nueva función.
Se puede lograr el mismo objetivo utilizando una función de ejecución automática "Expresión de función invocada inmediatamente, abreviatura: 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>