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 Windownesne 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 daveo ayarlar, böylece nesne thisiçin daveve çağıran getAgeişlevi. getAge()doğru şekilde geri dönecek 100.
JavaScript'te applyyö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ı bobnesne olarak manuel olarak geçiriyorsunuz. getAgeŞimdi dönecektir 200size denilen 'düşünce' rağmen getAgeüzerinde davenesne.
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();
ageMethodyürütme bir hata veriyor! Ne oldu?
Eğer dikkatlice benim yukarıdaki noktaları okursanız dikkat ediyorum dave.getAgeyöntemi ile çağrıldı daveolarak thisJavaScript için 'kapsam' belirleyemedi oysa nesne ageMethodyürütme. Böylece global 'Pencere'yi' bu 'olarak geçti. Şimdi windowolmadığı 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');
$windowas ile çağrılır thisve getElementByIduygulama bekliyorsathis olmakdocument , başarısız olur.
Yine bunu düzeltmek için yapabilirsin
$.apply(document, ['someElement']);
Peki neden Internet Explorer'da çalışıyor?
getElementByIdIE'de dahili uygulamasını bilmiyorum , ancak jQuery kaynağındaki ( inArrayyö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. PersonAş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();
};
}
PersonYukarıdaki işlev için, çeşitli getAgeyöntemlerin nasıl davranacağı aşağıda açıklanmıştır.
PersonFunction 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 yoginesneyi alır thisve çıktı alır 100.
var ageAlias = yogi.getAge;
console.log(ageAlias());
JavaScript yorumlayıcı windownesneyi olarak ayarlar thisve bizim getAgeyöntemimiz geri döner -1.
console.log(ageAlias.apply(yogi));
Doğru kapsamı ayarlarsak, ageAliasyö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());
ageSmarterFonksiyon orijinal yakalanan thisDoğ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));
ageSmartestGeçersiz bir kapsam verilir ise işlev orijinal kapsamını kullanacaktır.
console.log(ageSmartestAlias.apply(anotherYogi));
Yine de başka bir Personnesneye geçebileceksiniz getAgeSmartest. :)