Bu JavaScript / jQuery sözdizimi nasıl çalışır: (function (window, undefined) {}) (window)?


153

Hiç jQuery 1.4 kaynak kodundaki başlık altına bir göz attınız ve aşağıdaki şekilde nasıl kapsüllendiğini fark ettiniz mi :

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

JavaScript Ad Alanı ile ilgili bir makale ve " Önemli Bir Ebeveyn Parçası " başlıklı bir makale okudum , bu yüzden burada neler olduğu hakkında bir şeyler biliyorum.

Ama bu sözdizimini daha önce hiç görmedim. Orada ne undefinedyapıyor? Ve neden windowgeçilmeli ve daha sonra tekrar ortaya çıkmalı?


3
Paul Irish'ın
Mottie

@Bergi sorumu bir başkasının kopyası olarak işaretlediniz, ancak soruyu kopyadan neredeyse bir yıl önce sordum. Oyuncular tam tersi olmalı.
dkinzer

@dkinzer: Daha önce sorulmakla ilgili değil, en yüksek kalitede cevapla ilgili. Kuşkusuz, bu durumda boyun ve boyun, ama CMS'nin cevabının en iyisi olduğunu buldum. Bununla birlikte , sohbet etmek için chat.stackoverflow.com/rooms/17 adresine gelin
Bergi

Yanıtlar:


161

Undefined normal bir değişkendir ve ile kolayca değiştirilebilir undefined = "new value";. Böylece jQuery, GERÇEKTEN tanımsız olan bir yerel "tanımsız" değişken oluşturur.

Window değişkeni performans nedenleriyle yerel yapılır. Çünkü JavaScript bir değişkeni ararken değişken adını bulana kadar yerel değişkenlerden geçer. Bulunamadığı zaman, JavaScript genel değişkenleri filtreleyene kadar bir sonraki kapsamdan geçer. Dolayısıyla, pencere değişkeni yerel hale getirilirse, JavaScript bunu daha hızlı arayabilir. Daha fazla bilgi: JavaScript'inizi Hızlandırın - Nicholas C. Zakas


1
Teşekkürler! bu çok bilgilendirici bir videoydu. "Pencere değişkeni yerel yapılır" demek için yanıtınızı düzenlemeniz gerektiğini düşünüyorum. Bunun en iyi cevap olduğunu düşünüyorum. Saydım ve pencere nesnesi JQuery kaynak kodunda en az 17 kez çağrıldı bulundu. Bu yüzden pencereyi Yerel Kapsam'a taşımada önemli bir etki olmalı.
dkinzer

@DKinzer Oh evet, haklısın, tabii ki yerel yapılıyor. Sevindim size yardımcı olabilir =)
Vincent

1
Bu güncellenmiş teste göre jsperf.com/short-scope/5 geçen 'pencere' geçen jQuery ile bir pencere sabit almak için geldiğinde aslında daha yavaş ve özellikle Safari için kötü. Dolayısıyla 'undefined' bir kullanım senaryosuna sahip olsa da, 'window'un her durumda özellikle yararlı olduğuna pek ikna olmadım.
hexalys

1
Ayrıca kodu en aza indirmek için olumlu bir etkisi vardır. Böylece her "pencere" ve "tanımsız" kullanımı, küçültücü tarafından daha kısa bir adla değiştirilebilir.
TLindig

2
@ lukas.pukenis Milyonlarca web sitesinde kullanılan bir kütüphane oluştururken, delilerin ne yapacağına dair varsayımlar yapmamak akıllıca olur.
JLRishe

54

Tanımsız

undefinedBir argüman olarak ilan etmek , ama asla ona bir değer iletmemek, küresel kapsamda üzerine yazılabilecek bir değişken olduğu için her zaman tanımsız olmasını sağlar. Bu, birkaç karakter kazandıran a === undefinedgüvenli bir alternatif yapar typeof a == 'undefined'. Belge bununla birlikte kod daha minifier dostu yapar undefinediçin kısaltılabilir ubirkaç karakter tasarrufu, mesela.

pencere

windowBağımsız değişken olarak iletmek , performansı etkileyen yerel kapsamda bir kopya tutar: http://jsperf.com/short-scope . windowArtık tüm erişimlerin kapsam zincirinde bir seviye daha az seyahat etmesi gerekecek. Olduğu gibi undefined, yerel bir kopya daha agresif bir küçültmeye izin verir.


Kenar notu:

Bu, jQuery geliştiricilerinin niyeti olmasa da window, içeri aktarma , kütüphanenin sunucu tarafı Javascript ortamlarına, örneğin node.js'ye - global bir windownesnenin olmadığı daha kolay entegre edilmesine izin verir . Böyle bir durumda, windownesneyi başka bir tanesiyle değiştirmek için yalnızca bir satırın değiştirilmesi gerekir . JQuery durumunda, windowHTML kazıma amacıyla bir sahte nesne oluşturulabilir ve iletilebilir ( jsdom gibi bir kütüphane bunu yapabilir).


2
Minification bahsettiğiniz için +1, jsperf için +2 yapabilseydim - Minimize edilmiş sürüm (function(a,b){})(window);- ave bdaha kısa windowve undefined:)
gnarf

+1 Daha önce kapsam zincirini duymuştum , ama terimi unuttum. Teşekkürler!
alex

Aynı nedenden ötürü void (0) kullanılmasına bir alternatiftir: void (0), tanımlanmamış değeri elde etmenin güvenli bir yoludur.
glmxndr

"Ne diyorsun" diğer soruya atıfta bulunuyor: stackoverflow.com/questions/4945265/…
gnarf

@gnarf, soruların birleştirildiğine dair bildirim için teşekkürler. Biraz daha anlamlı olmak için cevabımı düzenleyeceğim;)
David Tang

16

Diğerleri açıkladı undefined. undefinedherhangi bir değere yeniden tanımlanabilen global bir değişken gibidir. Bu teknik, eğer birisi bir undefined = 10yerlerde , bir yerlerde bir şey yazdıysa, tanımlanmamış tüm kontrollerin kırılmasını önlemektir . Asla iletilmeyen bir argümanın undefined, değişkenin değerine bakılmaksızın gerçek olduğu garanti edilir undefined.

Pencereyi geçme nedeni aşağıdaki örnekle gösterilebilir.

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

Konsol ne kaydeder? windowNesnenin değeri doğru mu? Yanlış! 10? Yanlış! Günlüğe kaydeder undefined. Javascript yorumlayıcısı (veya JIT derleyicisi) bu şekilde yeniden yazar -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

Ancak, windowdeğişkeni bir argüman olarak alırsanız, var ve dolayısıyla sürpriz yoktur.

JQuery'nin bunu yapıp yapmadığını bilmiyorum, ancak windowyerel değişkeni herhangi bir nedenle işlevinizin herhangi bir yerinde yeniden tanımıyorsanız , küresel kapsamdan ödünç almak iyi bir fikirdir.


6

windowbirisinin IE'de pencere nesnesini yeniden tanımlamaya karar vermesi undefineddurumunda, daha sonra bir şekilde yeniden atanması durumunda , aynısını varsayıyorum .

Bu windowkomut dosyasındaki en üstte sadece "window" argümanı, global windowreferanstan daha yerel olan bir argüman ve bu kapanıştaki kodun kullanacağı isimlendiriliyor . windowSonunda aslında bu durumda, ilk argüman şu anki anlamını geçirmek için ne belirttiğini windowumut sen berbat değil ise ... windowbundan önce.

Bu eklenti, jQuery kullanılan en tipik durum göstererek düşünmek daha kolay olabilir .noConflict()bu yüzden kullanmaya devam edebilirsiniz kod çoğunluğu için, işleme $bir anlamı bile diğer daha jQuerybu kapsamı dışında:

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);

Teşekkürler. Bu çok mantıklı. Yine de, cevap bunun ve C.Zakas'ın söylediklerinin bir kombinasyonu olduğunu düşünüyorum.
dkinzer

@DKinzer Korkarım C. Değilim Zakas;)
Vincent

@Vincent, bunun için üzgünüm :-)
dkinzer

5

1000000 yineleme ile test edilmiştir. Bu tür yerelleştirmenin performans üzerinde hiçbir etkisi olmamıştır. 1000000 yinelemede tek bir milisaniye bile değil. Bu işe yaramaz.


2
Bahsetmemek gerekirse, closure tüm değişkenleri fonksiyon örneği ile birlikte taşır, bu nedenle 100 bayt ve 100kb daha fazla bellek olan 1000 örneğiniz varsa.
Akash Kava

@AkashKava ve @Semra, bu testin gerçek dünyada neden pencereden geçtiğinizi gerçekten açıkladığını düşünmüyorum. Performans kazancı yalnızca bu değişkenin kapsam zinciri boyunca daha ileriye erişen derin iç içe kapanışları olduğunda görülecektir. Açıkçası, fonksiyonunuz değişkenin kapsam zincirinde sadece bir adım uzaktaysa, fazla kazanç görmezsiniz. ama orada waaaay olsaydı ve almak gerekiyorsa, windowyerel bir kopya ile biraz kazanç görebilirsiniz.
gabereal

@gabereal yeni JavaScript motorları derleme sırasındaki kapanışları çözer, çalışma zamanında kapanmada performans kazancı yoktur. Ölçülebilir bir performans kazancı olduğundan şüpheliyim, eğer çok eminseniz, performansı göstermek için jsperf örneği oluşturabilirsiniz. Elde ettiğimiz tek performans, boyutu ve performansı azaltan daha iyi küçültme ile sonuçlanan kapanışları izole ederek, komut dosyasının daha hızlı indirilmesi ve ayrıştırılmasıyla elde edilir.
Akash Kava

@AkashKava Kendime bu kadar güvende olduğumu düşündüren şey nedir ? Sadece "biraz kazanç görebilir" ve "sanmıyorum" dedim. Bir test oluşturabilirdim, ama yine de bu kalıbı asla kullanmamam tercih etmem. "derleme sırasındaki kapanışları çözer" ile ne demek istediğinizi açıklayabilir misiniz? hangi alternatifin aksine? Javascript motorları işleri daha önce nasıl farklı yaptı?
gabereal

Pencerenin sonunda kıvrıldığı ancak işlevin parametrelerine girilmediği bir kod bul, ne anlama geliyor? varsaydığım herhangi bir pencere parametresi olmasa bile parametrelerin orijinal global kapsam nesnesini takip etmesini sağlıyor mu?
Webwoman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.