Bu özel davranışı anlamak için derinlere indim ve iyi bir açıklama bulduğumu düşünüyorum.
Neden takma ad yapamadığınıza girmeden önce document.getElementById
, JavaScript işlevlerinin / nesnelerinin nasıl çalıştığını açıklamaya çalışacağım.
Bir JavaScript işlevini her çalıştırdığınızda, JavaScript yorumlayıcısı bir kapsam belirler ve bunu işleve aktarır.
Aşağıdaki işlevi düşünün:
function sum(a, b)
{
return a + b;
}
sum(10, 20);
Bu işlev Pencere kapsamında bildirilir ve onu çağırdığınızda this
, toplam işlevinin içindeki değer global Window
nesne olur.
"Toplam" işlevi için, kullanmadığı için "bu" değerinin ne olduğu önemli değildir.
Aşağıdaki işlevi düşünün:
function Person(birthDate)
{
this.birthDate = birthDate;
this.getAge = function() { return new Date().getFullYear() - this.birthDate.getFullYear(); };
}
var dave = new Person(new Date(1909, 1, 1));
dave.getAge();
Eğer dave.getAge işlevini çağırdığınızda JavaScript yorumlayıcısı, üzerinde getAge işlevini çağırarak olduğunu görür dave
o ayarlar, böylece nesne this
için dave
ve çağıran getAge
işlevi. getAge()
doğru şekilde geri dönecek 100
.
JavaScript'te apply
yöntemi kullanarak kapsamı belirtebileceğinizi biliyor olabilirsiniz . Hadi deneyelim.
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
dave.getAge.apply(bob);
Yukarıdaki satırda, kapsama JavaScript'in karar vermesine izin vermek yerine, kapsamı bob
nesne olarak manuel olarak geçiriyorsunuz. getAge
Şimdi dönecektir 200
size denilen 'düşünce' rağmen getAge
üzerinde dave
nesne.
Yukarıdakilerin hepsinin anlamı nedir? İşlevler, JavaScript nesnelerinize 'gevşek bir şekilde' eklenir. Örneğin yapabilirsin
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
bob.getAge = function() { return -1; };
bob.getAge();
dave.getAge();
Bir sonraki adıma geçelim.
var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;
dave.getAge();
ageMethod();
ageMethod
yürütme bir hata veriyor! Ne oldu?
Eğer dikkatlice benim yukarıdaki noktaları okursanız dikkat ediyorum dave.getAge
yöntemi ile çağrıldı dave
olarak this
JavaScript için 'kapsam' belirleyemedi oysa nesne ageMethod
yürütme. Böylece global 'Pencere'yi' bu 'olarak geçti. Şimdi window
olmadığı gibibirthDate
özelliği ,ageMethod
yürütme başarısız olacaktır.
Bunu nasıl düzeltebilirim? Basit,
ageMethod.apply(dave);
Yukarıdakilerin tümü mantıklı mıydı? Varsa, neden takma ad yapamadığınızı açıklayabileceksiniz document.getElementById
:
var $ = document.getElementById;
$('someElement');
$
window
as ile çağrılır this
ve getElementById
uygulama bekliyorsathis
olmakdocument
, başarısız olur.
Yine bunu düzeltmek için yapabilirsin
$.apply(document, ['someElement']);
Peki neden Internet Explorer'da çalışıyor?
getElementById
IE'de dahili uygulamasını bilmiyorum , ancak jQuery kaynağındaki ( inArray
yöntem uygulaması) bir yorum , IE'de window == document
. Eğer durum buysa, takma addocument.getElementById
IE'de çalışmalıdır.
Bunu daha da açıklamak için ayrıntılı bir örnek oluşturdum. Person
Aşağıdaki işleve bir göz atın .
function Person(birthDate)
{
var self = this;
this.birthDate = birthDate;
this.getAge = function()
{
if(this.constructor == Person)
return new Date().getFullYear() - this.birthDate.getFullYear();
else
return -1;
};
this.getAgeSmarter = function()
{
return self.getAge();
};
this.getAgeSmartest = function()
{
var scope = this.constructor == Person ? this : self;
return scope.getAge();
};
}
Person
Yukarıdaki işlev için, çeşitli getAge
yöntemlerin nasıl davranacağı aşağıda açıklanmıştır.
Person
Function kullanarak iki nesne oluşturalım .
var yogi = new Person(new Date(1909, 1,1));
var anotherYogi = new Person(new Date(1809, 1, 1));
console.log(yogi.getAge());
Açıkçası, getAge yöntemi yogi
nesneyi alır this
ve çıktı alır 100
.
var ageAlias = yogi.getAge;
console.log(ageAlias());
JavaScript yorumlayıcı window
nesneyi olarak ayarlar this
ve bizim getAge
yöntemimiz geri döner -1
.
console.log(ageAlias.apply(yogi));
Doğru kapsamı ayarlarsak, ageAlias
yöntemi kullanabilirsiniz .
console.log(ageAlias.apply(anotherYogi));
Başka bir kişi nesnesini geçersek, yine de yaşı doğru hesaplayacaktır.
var ageSmarterAlias = yogi.getAgeSmarter;
console.log(ageSmarterAlias());
ageSmarter
Fonksiyon orijinal yakalanan this
Doğru kapsamını sunma hakkında endişe zorunda kalmamak için şimdi nesne.
console.log(ageSmarterAlias.apply(anotherYogi));
Sorun ageSmarter
şu ki, kapsamı başka bir nesneye asla ayarlayamazsınız.
var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias());
console.log(ageSmartestAlias.apply(document));
ageSmartest
Geçersiz bir kapsam verilir ise işlev orijinal kapsamını kullanacaktır.
console.log(ageSmartestAlias.apply(anotherYogi));
Yine de başka bir Person
nesneye geçebileceksiniz getAgeSmartest
. :)