Gönderen docs Anlıyorum .proxy()argüman olarak iletilen fonksiyonun kapsamını değiştirecektir. Birisi bana bunu daha iyi açıklayabilir mi? Bunu neden yapalım?
Gönderen docs Anlıyorum .proxy()argüman olarak iletilen fonksiyonun kapsamını değiştirecektir. Birisi bana bunu daha iyi açıklayabilir mi? Bunu neden yapalım?
Yanıtlar:
Sonuçta yaptığı şey this, bir fonksiyondaki değerin arzu ettiğiniz değer olmasını sağlamaktır.
Yaygın bir örnek, setTimeoutbir clickişleyicinin içinde yer alan bir örnektir .
Bunu al:
$('#myElement').click(function() {
// In this function, "this" is our DOM element.
$(this).addClass('aNewClass');
});
Niyet yeterince basit. Ne zaman myElementtıklandığında, bu sınıf almalısınız aNewClass. İşleyicinin içinde thistıklanan öğeyi temsil eder.
Ama ya dersi eklemeden önce kısa bir gecikme isteseydik? Bunu setTimeoutbaşarmak için a'yı kullanabiliriz , ama sorun şu ki setTimeout, verdiğimiz fonksiyon ne olursa olsun , thisbu fonksiyonun içindeki değerin windowelemanımız yerine olması.
$('#myElement').click(function() {
setTimeout(function() {
// Problem! In this function "this" is not our element!
$(this).addClass('aNewClass');
}, 1000);
});
Bunun yerine, yapabileceğimiz, $.proxy()onu atamak istediğimiz işlevi ve değeri göndererek çağırmaktır ve bu değeri thiskoruyacak bir işlev döndürür.
$('#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
});
Bu nedenle $.proxy(), işlevi ve istediğimiz değeri verdikten sonra , düzgün bir şekilde ayarlanmasını thissağlayacak bir işlev döndürdü this.
Bunu nasıl yapıyor? Sadece açıkça değerini ayarlamasını sağlayan yöntemi kullanarak fonksiyonumuzu çağıran anonim bir fonksiyon döndürür ..apply()this
Döndürülen işleve basitleştirilmiş bir görünüm şöyle görünebilir:
function() {
// v--------func is the function we gave to $.proxy
func.apply( ctx );
// ----------^------ ctx is the value we wanted for "this" (our DOM element)
}
Yani bu anonim işleve verilir setTimeoutve tüm yaptığı şey orijinal fonksiyonumuzu uygun thisbağlamda yürütmektir .
$.proxy(function () {...}, this)yerine kullanmanın değeri nedir (function() {...}).call(this)? Bir fark var mı?
.callsizinle fonksiyonu hemen çağırıyorsunuz. İle $.proxy, Function.prototype.bindyeni bir işlev döndürdüğü yere benzer . Bu yeni işlevin thisdeğeri kalıcı olarak bağlıdır, böylece iletildiğinde setTimeoutve setTimeoutişlevi daha sonra çağırdığında yine de doğru thisdeğere sahip olur.
Daha fazla ayrıntıya girmeden ( ECMAScript'teki Bağlam , bu bağlam değişkeni vb . İle ilgili olduğu için gerekli olacaktır )
ECMA- / Javascript'te üç farklı tür "Bağlam" vardır:
Her kod yürütme bağlamında yürütülür . Tek bir küresel bağlam vardır ve birçok işlev (ve değerlendirme) bağlamı örneği olabilir. Şimdi ilginç kısım:
Bir işlevin her çağrılması işlev yürütme bağlamına girer. Bir işlevin yürütme bağlamı şöyle görünür:
Aktivasyon Nesnesi
Kapsam Zinciri
bu değer
Dolayısıyla bu değer, yürütme bağlamıyla ilgili özel bir nesnedir. ECMA- / Javascript içinde bir işlev yürütme bağlamında bu değeri değiştirebilecek iki işlev vardır :
.call()
.apply()
Bir fonksiyonumuz varsa foobar(), bu değeri arayarak değiştirebiliriz:
foobar.call({test: 5});
Şimdi geçtiğimiz foobarnesneye erişebildik :
function foobar() {
this.test // === 5
}
Aynen jQuery.proxy()öyle. Bir functionve context(bir nesneden başka bir şey değildir) alır ve işlevi çağırarak .call()veya .apply()bu yeni işlevi döndürerek işlevi bağlar .
Aynı hedefe "Hemen Başlatılan İşlev İfadesi, kısa: IIFE" kendi kendini yürütme işlevi kullanılarak da ulaşılabilir :
$('#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>