Da documenti ho capito che .proxy()cambierebbe l'ambito della funzione passata come argomento. Qualcuno potrebbe spiegarmi meglio? Perché dovremmo farlo?
Da documenti ho capito che .proxy()cambierebbe l'ambito della funzione passata come argomento. Qualcuno potrebbe spiegarmi meglio? Perché dovremmo farlo?
Risposte:
Ciò che alla fine fa è assicurarsi che il valore di thisin una funzione sia il valore desiderato.
Un esempio comune è in un setTimeoutche si svolge all'interno di un clickgestore.
Prendi questo:
$('#myElement').click(function() {
// In this function, "this" is our DOM element.
$(this).addClass('aNewClass');
});
L'intenzione è abbastanza semplice. Quando myElementviene cliccato, dovrebbe ottenere la classe aNewClass. All'interno del gestore thisrappresenta l'elemento su cui è stato fatto clic.
E se volessimo un breve ritardo prima di aggiungere la classe? Potremmo usare a setTimeoutper realizzarlo, ma il guaio è che qualunque sia la funzione che diamo setTimeout, il valore thisall'interno di quella funzione sarà windowinvece del nostro elemento.
$('#myElement').click(function() {
setTimeout(function() {
// Problem! In this function "this" is not our element!
$(this).addClass('aNewClass');
}, 1000);
});
Quindi quello che possiamo fare, invece, è chiamare $.proxy(), inviandogli la funzione e il valore che vogliamo assegnare thise restituirà una funzione che manterrà quel valore.
$('#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
});
Quindi dopo che abbiamo dato $.proxy()la funzione e il valore che desideriamo this, ha restituito una funzione che garantirà che thissia impostata correttamente.
Come lo fa? Restituisce semplicemente una funzione anonima che chiama la nostra funzione utilizzando il .apply()metodo, che consente di impostare esplicitamente il valore di this.
Uno sguardo semplificato alla funzione che viene restituita può apparire come:
function() {
// v--------func is the function we gave to $.proxy
func.apply( ctx );
// ----------^------ ctx is the value we wanted for "this" (our DOM element)
}
Quindi questa funzione anonima è data a setTimeout, e tutto ciò che fa è eseguire la nostra funzione originale nel giusto thiscontesto.
$.proxy(function () {...}, this)piuttosto che (function() {...}).call(this)? C'è una differenza?
.callte stai chiamando immediatamente la funzione. Con $.proxy, è come Function.prototype.binddove restituisce una nuova funzione. Quella nuova funzione ha il thisvalore associato in modo permanente, in modo che quando viene passato a setTimeout, e setTimeoutchiama la funzione in seguito, avrà ancora il thisvalore corretto .
Senza entrare nel dettaglio (ciò sarebbe necessario perché si tratta di Contesto in ECMAScript, questa variabile di contesto ecc.)
Esistono tre diversi tipi di "contesti" in ECMA- / Javascript:
Ogni codice viene eseguito nel suo contesto di esecuzione . Esiste un contesto globale e possono esserci molti casi di contesti di funzione (e valutazione). Ora la parte interessante:
Ogni chiamata di una funzione entra nel contesto di esecuzione della funzione. Un contesto di esecuzione di una funzione è simile a:
L'ambito Activation Object
Scope
questo valore
Quindi questo valore è un oggetto speciale correlato al contesto di esecuzione. Esistono due funzioni in ECMA- / Javascript che possono modificare questo valore in un contesto di esecuzione della funzione:
.call()
.apply()
Se abbiamo una funzione foobar()possiamo cambiare questo valore chiamando:
foobar.call({test: 5});
Ora potremmo accedere foobarall'oggetto in cui siamo passati:
function foobar() {
this.test // === 5
}
Questo è esattamente ciò che jQuery.proxy()fa. Prende un functione context(che non è altro che un oggetto) e collega la funzione invocando .call()o .apply()e restituisce quella nuova funzione.
Lo stesso obiettivo può essere raggiunto utilizzando una funzione di auto-esecuzione "Espressione di funzione immediatamente richiamata, breve: 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>