Ünlem işareti işlevden önce ne yapar?


1242
!function () {}();

4
@Dykam Yararlılığı bu cevapta açıklanmıştır: stackoverflow.com/questions/5422585/…
hectorct



7
@befzz Bu makaleye daha sonra açıklandığı üzere, hemen çağrılan bir İşlev İfadesi olarak adlandırmak daha iyidir ("kendi kendini yürüten" özyineleme anlamına gelir)
Zach Esposito

Yanıtlar:


2117

JavaScript sözdizimi 101. İşte bir işlev bildirimi :

function foo() {}

Noktalı virgül olmadığını unutmayın: bu yalnızca bir işlev bildirimidir . foo()İşlevi gerçekten çalıştırmak için bir çağrıştırmaya ihtiyacınız vardır .

Şimdi, görünüşte zararsız bir ünlem işareti eklediğimizde: !function foo() {}bunu bir ifadeye dönüştürüyor . Artık bir işlev ifadesidir .

!Tek başına elbette fonksiyonu çağırmak değil, ama şimdi koyabilirsiniz ()sonunda: !function foo() {}()daha yüksek önceliğe sahiptir !ve anında işlevini çağırır.

Yani yazarın yaptığı her fonksiyon ifadesi başına bir bayt kaydetmek; daha okunabilir bir şekilde yazılması şöyle olur:

(function(){})();

Son olarak, !ifadeyi doğru yapar. Bunun nedeni, varsayılan olarak undefined, bizi bırakan tüm IIFE dönüşlerinin !undefinedolmasıdır true. Özellikle yararlı değil.


229
+1. Bu gerçekten buradaki en iyi cevap ve ne yazık ki zorlukla kaldırıldı. Açıkçası, !boolean döndürür, hepimiz biliyoruz, ancak yaptığınız en büyük nokta, işlev bildirim deyimini bir işlev ifadesine dönüştürmesi ve böylece işlevin parantez içine alınmadan hemen çağrılmasıdır. Açık değil ve açıkça kodlayıcının amacı.
gilly3

64
+1 Bu, NEDEN bunu yapmak isteyeceğinize ve bunun neden geri dönüş sonucunun olumsuzlanmasından daha fazlasını kullandığını ele alan tek cevaptır. Tekli operatör! (ayrıca ~, - ve +) işlev bildiriminden ayrılır ve sondaki () öğelerin, işlevi yerinde çağırmasını sağlar. Bu genellikle modüler kod yazarken değişkenler için yerel bir kapsam / ad alanı oluşturmak için yapılır.
Tom Auger

65
Bir başka yararı da! noktalı virgül eklemeye neden olur, bu nedenle bu sürümün; ile bitmeyen bir dosyayla yanlış birleştirilmesi imkansızdır. () Formunuz varsa, bunu önceki dosyada tanımlanmış olanın işlev çağrısı olarak görür. Bir iş arkadaşım için şapkanın ucu.
Jure Triglav

5
@Carnix var foo =ifade / ifade belirsizliğini bozar ve yazabilirsiniz var foo = function(bar){}("baz");vb.
Neil

6
Bu genellikle her bir baytın sayıldığı minyatür / çirkinleştirme komut dosyaları ile yapılır.
Dima Slivin

367

İşlev:

function () {}

hiçbir şey döndürmez (veya tanımsız).

Bazen bir işlevi yarattığımız gibi çağırmak isteriz. Bunu denemek cazip olabilir:

function () {}()

ancak a SyntaxError.

Kullanılması !fonksiyonu bir ifadesi olarak tedavi edilecek bunu neden daha önce bu yüzden biz onu çağırabilir, operatörünü:

!function () {}()

Bu aynı zamanda bu durumda, fonksiyonun dönüş değerinin boolean tersini dönecektir true, çünkü !undefinedolduğunu true. Gerçek dönüş değerinin çağrının sonucu olmasını istiyorsanız, bu şekilde yapmayı deneyin:

(function () {})()

28
buna kim ihtiyaç duyabilir?
Andrey

13
bu sadece bravo, söz konusu davayı açıklıyor cevap!
Andrey

14
İkinci kod örneğiniz geçerli JavaScript değil. Bunun amacı !, işlev bildirimini bir işlev ifadesine dönüştürmektir, hepsi bu.
Skilldrick

8
@Andrey Bootstrap twitter bunu tüm javascript (jQuery) eklenti dosyalarında kullanır. Başkalarının da aynı soruyu sorması ihtimaline karşı bu yorumu eklemek.
Anmol Saraf

2
d3.js ayrıca !functionsözdizimini kullanır
Kristian

65

Airbnb JavaScript rehberinde! işaretlenmiş işlev çağırma için iyi bir nokta var

Genel olarak bu tekniği daha sonra birleştirilecek ayrı dosyalarda (aka modüller) kullanma fikri. Buradaki uyarı, yeni dosyayı yeni satıra yerleştiren araçlarla birleştirilmesi gereken dosyalardır (bu, zaten birçok concat aracının ortak davranışıdır). Bu durumda, !daha önce birleştirilmiş modül sondaki noktalı virgül özlediyse, hatadan kaçınmaya yardımcı olur ve yine de bunları endişelenmeden herhangi bir sıraya koyma esnekliği verir.

!function abc(){}();
!function bca(){}();

İle aynı şekilde çalışacaktır

!function abc(){}();
(function bca(){})();

ancak bir karakteri kaydeder ve keyfi olarak daha iyi görünür.

Ve bu arada herhangi biri tarafından +, -, ~, voidonlar farklı hareket edeceğini işlevinden dönmek için bir şey kullanmak zorunda eğer operatörleri kesin, fonksiyonu çağıran açısından, aynı etkiye sahiptir.

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

ancak bir dosya için bir modül kod ayırma için IIFE kalıpları kullanıyorsanız ve optimizasyon için concat aracını (bir satır bir dosya işi yapan) kullanıyorsanız, o zaman inşaat

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

İlk kod örneğinde olduğu gibi güvenli kod yürütme işlemini gerçekleştirir.

Bu hata JavaScript ASI işini yapamaz neden olur hata atar.

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

Tekli operatörlerle ilgili bir not, benzer işler yapacaklardı, ancak sadece durumda, ilk modülde kullanmamışlardı. Bu yüzden, birleştirme sırası üzerinde tam kontrole sahip değilseniz, o kadar güvenli değildir.

Bu çalışıyor:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

Bu değil:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()

3
Aslında, bu diğer semboller aynı etkiye sahip değildir. Evet, bir işlevi açıklandığı gibi çağırmanıza izin verir, ancak aynı değildir. Şunu düşünün: var foo =! Function (bar) {console.debug (bar); } ( "BAT"); Hangi sembollerin önüne koyarsanız koyun, konsolunuzda "yarasa" alırsınız. Şimdi console.debug ("foo:", foo) ekleyin; - kullandığınız sembole bağlı olarak çok farklı sonuçlar elde edersiniz. ! her zaman arzu edilmeyen bir dönüş değerini zorlar. Netlik ve doğruluk için ({}) () sözdizimini tercih ederim.
Carnix

29

İfadenin false olarak değerlendirilip değerlendirilemeyeceğini döndürür. Örneğin:

!false      // true
!true       // false
!isValid()  // is not valid

Bir değeri boole değerine zorlamak için iki kez kullanabilirsiniz:

!!1    // true
!!0    // false

Sorunuzu daha doğrudan yanıtlamak için:

var myVar = !function(){ return false; }();  // myVar contains true

Düzenle: İşlev bildirimini bir işlev ifadesine değiştirmenin yan etkisi vardır. Örneğin, aşağıdaki kod geçerli değildir, çünkü gerekli tanımlayıcıyı (veya işlev adını ) içermeyen bir işlev bildirimi olarak yorumlanır :

function () { return false; }();  // syntax error

6
Hemen çağrılmış bir işleve sahip bir ödev kullanmak isteyen okuyucular için netlik sağlamak amacıyla örnek kodunuz benzerleri var myVar = !function(){ return false; }()atlayabilir ve işlev doğru şekilde yürütülür ve dönüş değerine dokunulmaz. !var myVar = function(){ return false; }()
Mark Fox

1
Açık olmak gerekirse, bir kez Boole'ye zorlamak için kullanabilirsiniz, çünkü bu mantıksal değil operatördür. ! 0 = doğru ve! 1 = yanlış. JavaScript küçültme amacıyla, değiştirmek isterdim trueile !0ve falseile !1. 2 veya 3 karakter kaydeder.
Triynko

9

Javascript küçültme yaparken sadece bir bayt veri kaydetmek içindir.

aşağıdaki anonim işlevi göz önünde bulundurun

function (){}

Yukarıdakileri kendi kendini çağırma fonksiyonu olarak yapmak için genellikle yukarıdaki kodu şu şekilde değiştireceğiz:

(function (){}())

Şimdi fonksiyonu çağırmak için gerekli olan fonksiyonun sonuna (,)eklemek dışında iki ekstra karakter ekledik (). Küçültme sürecinde genellikle dosya boyutunu küçültmeye odaklanırız. Böylece yukarıdaki işlevi de yazabiliriz

!function (){}()

Yine de her ikisi de kendi kendini çağıran işlevlerdir ve biz de bir bayt tasarruf ediyoruz. 2 karakter yerine (,)sadece bir karakter kullandık!


1
Bu yararlı olur, çünkü bunu genellikle küçültülmüş js'de görürsünüz
Ad

5

! mantıklı bir NOT işleci, bir şeyi tersine çevirecek bir boolean işleci.

İşlevden önce BANG (!) Kullanarak çağrılan işlevin parantezlerini atlayabilmenize rağmen , yine de istediğinizi döndürmeyecek şekilde dönüşü tersine çevirecektir. Bir IEFE örneğinde olduğu gibi, tersine çevrildiğinde boole gerçeği haline gelen tanımsız dönecektir .

Bunun yerine, gerekirse kapanış parantezini ve BANG'ı ( ! ) Kullanın .

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening.

(function(){ return false; }());
=> false

!(function(){ return false; }());
=> true

!!(function(){ return false; }());
=> false

!!!(function(){ return false; }());
=> true

Çalışan Diğer Operatörler ...

+(function(){ return false; }());
=> 0

-(function(){ return false; }());
=> -0

~(function(){ return false; }());
=> -1

Kombine Operatörler ...

+!(function(){ return false; }());
=> 1

-!(function(){ return false; }());
=> -1

!+(function(){ return false; }());
=> true

!-(function(){ return false; }());
=> true

~!(function(){ return false; }());
=> -2

~!!(function(){ return false; }());
=> -1

+~(function(){ return false; }());
+> -1

5

Ünlem işareti herhangi bir işlevin her zaman bir boole döndürmesini sağlar.
Son değer, işlev tarafından döndürülen değerin reddedilmesidir.

!function bool() { return false; }() // true
!function bool() { return true; }() // false

Atlanması !Yukarıdaki örneklerde, bir olacaktır SyntaxError .

function bool() { return true; }() // SyntaxError

Ancak, bunu başarmanın daha iyi bir yolu:

(function bool() { return true; })() // true

Bu yanlış. !çalışma zamanının işlevi ayrıştırma biçimini değiştirir. Çalışma zamanının işleve bir işlev ifadesi gibi davranmasını sağlar (bir bildirim değil). Bunu, geliştiricinin ()sözdizimini kullanarak işlevi hemen çağırmasını sağlamak için yapar . !işlev ifadesini çağırmanın sonucuna da kendisini (yani olumsuzlama) uygulayacaktır.
Ben Aston

3

IIFE (hemen çağrılmış fonksiyon ifadesi) yazmanın başka bir yolu.

Diğer yazı biçimi -

(function( args ) {})()

ile aynı

!function ( args ) {}();

Tamamen aynı değil; 2. form işlev çağrısının sonucunu reddeder (ve sonra değer ataması olmadığı için onu atar). Kesinlikle daha açık (function (args) {...})()sözdizimini tercih eder ve bu !functionformu küçültme ve gizleme araçlarına bırakırım .
Tobias

-1

! sonuç olarak beklediğiniz her şeyi reddeder (tersine), yani

var boy = true;
undefined
boy
true
!boy
false

aradığınızda boy, sonucunuz olur true, ancak !aramayı eklediğiniz an boy, yani !boysonucunuz olur false. Başka bir deyişle NotBoy'u kastediyorsunuz , ama bu sefer temelde boolean bir sonuç ya trueda false.

!function () {}();İfadede olanla aynı şey, sadece koşmak function () {}();size bir hata işaretleyecek, ancak ifadenizin !tam önüne ekleyecek function () {}();, bunu function () {}();size geri dönecek olanın tersi yapıyor true. Örnek aşağıda görülebilir:

function () {}();
SyntaxError: function statement requires a name
!function () {}();
true
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.