javascript işlevi lider patlama! sözdizimi


204

Bu sözdizimini birkaç kütüphanede görüyorum ve bunun ne faydası olduğunu merak ediyorum. (Ben iyi kapanışları ve kodun ne yaptığını biliyorum, ben sadece sözdizimsel farklılıkları hakkında endişe)

!function(){
  // do stuff
}();

Daha yaygın olanlara alternatif olarak

(function(){
  // do stuff
})();

kendiliğinden çalışan anonim işlevler için.

Birkaç şey merak ediyorum. İlk olarak, en iyi örneğin gerçekten çalışmasına izin veren nedir? Bu ifadeyi sözdizimsel olarak doğru hale getirmek için patlama neden gereklidir? Bana bunun +işe yaradığı söylendi ve eminim bazılarının yerine!

İkincisi, faydası nedir? Tek söyleyebileceğim tek bir karakter kurtardığı, ancak bunun çok sayıda evlat edinen için büyük bir fayda olduğunu hayal edemiyorum. Kaybettiğim başka bir fayda var mı?

Görebildiğim diğer tek fark, kendini çağırma işlevinin dönüş değeri olacaktır, ancak bu örneklerin her ikisinde de, yalnızca bir kapatma oluşturmak için kullanıldığından işlevin dönüş değerini gerçekten umursamıyoruz. Birisi bana neden birinin ilk sözdizimini kullanabileceğini söyleyebilir mi?


Çerçeveler, bir küçültücünün optimize edemeyeceği kadar çok karakter kaydetmeyi sever.
alex

İlk fayda kafama geliyor, (fonksiyon ($) {...}) (jQuery) gibi bir sanal alan oluşturabilirsiniz;
JS Taylor

2
her iki örnek de bunu başarır. Belirtildiği gibi, bu işlevlerin ne yaptığını anlıyorum, sözdizimsel farklılıklarla daha fazla ilgileniyorum
brad

8
Bir önceki mürettebata göre daha sofistike bir şekilde sevimli olma ihtiyacına, nee, gereksinime bağlıyorum. "Ah, şu parantezli dinsizler, elimizde !!"
Jared Farrish

2
Bunu hiç bilmiyordum, harika. !Yapıldığını vurguladığı gibi seviyorum .
cdmckay

Yanıtlar:


97

İdeal olarak, tüm bunları basitçe şu şekilde yapabilmelisiniz:

function(){
  // do stuff
}(); 

Bu, anonim işlevi bildirmek ve yürütmek demektir. Ancak bu, JS dilbilgisinin özellikleri nedeniyle çalışmaz.

Bunu başarmanın en kısa yolu bazı ifadeler kullanmaktır, örneğin UnaryExpression (ve bu yüzden CallExpression):

!function(){
  // do stuff
}(); 

Veya eğlence için:

-function(){
  // do stuff
}(); 

Veya:

+function(){
  // do stuff
}(); 

Ya da:

~function(){
  // do stuff
  return 0;
}( );

3
Peki o zaman tek fayda terslik?
brad

12
Yukarıdaki tüm seçenekleri performans testine ekledim
Shaz

5
Anlatım söyleyebilirim. Hız, bir kez çalıştığı durumlarda gerçekten önemli değildir.
c-smile

1
Meraktan, hiçbir patlamanın ve patlamanın en hızlı performansı göstermediğini fark ettim, ancak en azından Chrome'un evriminde bir yerde, patlama patlamadan daha hızlı hale geldi. (Muhtemelen istatistiksel olarak önemsiz ama ...) Bunun bir nedeni var mı? Kaputun altındaki kod hakkında çok şey bilmiyorum ama oldukça büyüleyici buluyorum.
jmk2142

Noktalı virgül eksikse, tekli operatörlerinizden ikisi ikili olarak yorumlanabilir. Birincisi ve sonuncusu bu örneklerin en güvenli olanlarıdır.

73

Javascript'te, ile başlayan bir satırın functionbir işlev ifadesi olması beklenir ve

function doSomething() {
}

Kendini çağıran bir işlev

function(){
  // do stuff
}();

bu forma sığmaz (ve işlev adı olmadığından ilk açılış pareninde bir sözdizimi hatasına neden olur), bu nedenle köşeli parantezler anonim bir işlev ifadesini tanımlamak için kullanılır .

(function(){
  // do stuff
})();

Fakat bir ifade yaratan her şey (bir işlev ifadesinin aksine) bunu yapar, dolayısıyla !. Tercümana bunun bir işlev ifadesi olmadığını söylüyor. Bunun dışında, operatör önceliği işlevin olumsuzlamadan önce çağrıldığını belirtir.

Bu sözleşmenin farkında değildim, ancak yaygınlaşırsa okunabilirliğe katkıda bulunabilir. Demek istediğim, !functionbüyük bir kod bloğunun üst kısmında okuyan herkesin kendini çağırma beklediği, gördüğümüzde zaten aynı şeyi beklememiz şart (function. Ancak o sinir bozucu parantezleri kaybedeceğiz. Hız veya karakter sayısındaki herhangi bir tasarrufun aksine, bu yüzden beklerdim.


Bu "işlevle başlayan çizgi bekleniyor ..." oldukça bulanık görünüyor. Buna ne dersiniz:var foo = {CR/LF here} function bar() {}
c-smile

45

Zaten söylenen şeylerin yanı sıra,! noktalı virgül olmadan javascript yazarsanız yararlıdır:

var i = 1
!function(){
  console.log('ham')
}()

i = 2
(function(){
  console.log('cheese')
})()

İlk örnek beklendiği gibi 'ham' çıktısını verir, ancak i = 2 ifadesi aşağıdaki parantez nedeniyle sonlandırılmadığından ikincisi hata verir.

Ayrıca birleştirilmiş javascript dosyalarında, önceki kodda noktalı virgül yoksa endişelenmenize gerek yoktur. Yani ortak olana gerek yok; (function () {}) (); kendinizin kırılmayacağından emin olmak için.

Cevabımın biraz geç olduğunu biliyorum ama sanırım henüz bahsedilmedi :)


6
Bahşiş ve anılar için +1 ... bugünlerde kimse noktalı virgül kullanmadan javascript yazmayı sevmiyor.
Pablo Grisafi

4
Twitter Bootstrap, noktalı virgül içermeyen tüm JS'dir ve oldukça yenidir ... (yukarıdaki yorum doğada alaycı ve özledim özür dilerim).
brandwaffle

2
Bu aslında doğru değil. Aşağıdaki örneği düşünün:! Function () {console.log ("ham");} ()! Function () {console.log ("cheese")} (); bir hata alırsınız: "SyntaxError: Beklenmedik belirteç!"
heavysixer

Evet haklısın. Bunları aynı satıra koyarsanız bir hata var. Bunu düşünmedim. Ancak, şimdiye kadar kullandığım hiçbir bitiştirme komut dosyası / lib bunu yapmaz. Ve dosyalarınızı küçültüp bitirdiğinizde noktalı virgül eklenir. Dürüst olmak gerekirse, bu problemle karşılaşacağınız bir durumu hayal edemiyorum. Öte yandan, burada 02:00 ve cahil olabilir :)
Smoe

6

Bir kere, jsPerf !(UnaryExpression) kullanmanın genellikle daha hızlı olduğunu gösterir. Bazen eşit olmaya gelirler, ancak değilken, çarptım olmayan bir zaferi henüz diğerleri üzerinde çok fazla görmedim : http://jsperf.com/bang-function

Bu, en eski Ubuntu'da test edilmiştir (her biri için ..) Chrome, sürüm 8 ile.

Edit: Nasıl deli gibi bir şey delete?

delete function() {
   alert("Hi!"); 
}();

veya void?

void function() {
   alert("Hi!"); 
}();

ilginç! Safari hız-bilge olsa, yaklaşık 50/50 var, çarptım kesinlikle kendi tuttu. Merak ediyorum, potansiyel hız farklılıklarına dair bir teori var mı?
brad

@brad Safari ile ilgili bir şey olmalı, testlere bakarsanız, diğer tarayıcıların çoğu tercih ediyor gibi görünüyor !. Ama ben de bu konuda bir teori bulmak istiyorum :)
Shaz

3
açıkça "i dönüş değeri umurumda değil" diyor çünkü void gibi ve diğer dillerde sözleşmeler hatırlatıyor çünkü
code_monk

4

Gördüğünüz gibi burada , kullandığı javascript kendini çağrılan yöntemleri yapmanın en iyi yolu:

(function(){}()); -> 76,827,475 ops/sec

!function(){}();  -> 69,699,155 ops/sec

(function(){})(); -> 69,564,370 ops/sec

1
Performansın bir sözdizimini veya diğerini kullanmanın sebebi olduğundan şüpheliyim. 70M ops / sn'de, kapanışın zaten içindeki koddan binlerce kat daha hızlı olacağını bildirmek
Eloims

3

Yani, olumsuzluk "!" +, -, ~ gibi tüm tekli operatörlere sil, geçersiz, çok fazla şey söylendi, sadece özetle:

!function(){
  alert("Hi!");
}(); 

Veya

void function(){
  alert("Hi!");
}();

Veya

delete function(){
  alert("Hi!");
}();

Ve ikili operatörlerle ilgili birkaç örnek daha eğlence için :)

1 > function() {
   alert("Hi!"); 
}();

Veya

1 * function() {
   alert("Hi!"); 
}();

Veya

1 >>> function() {
   alert("Hi!"); 
}();

Ya da

1 == function() {
   alert("Hi!"); 
}();

Üçüncüyü başkası için terk etmek çocuklar :)


12
0?0:function() { alert("Hi!"); }();
daniel1426

Bingo, Dan! Üçlü var;)
Arman McHitarian
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.