Anonim JavaScript işlevlerini otomatik olarak yürütmek için parantez konumu?


107

Yakın zamanda json2.js'nin mevcut sürümünü projemdeki sürümle karşılaştırıyordum ve işlev ifadesinin nasıl oluşturulduğu ve kendiliğinden yürütüldüğü konusunda bir fark gördüm.

Anonim bir işlevi parantez içine almak ve ardından çalıştırmak için kullanılan kod,

(function () {
  // code here
})();

ancak şimdi otomatik olarak yürütülen işlevi parantez içine alıyor.

(function () {
  // code here
}());

Açıkla JavaScript'in kapsüllenmiş anonim işlev söz diziminin kabul edilen yanıtında CMS tarafından "hem: (function(){})();hem (function(){}());de geçerli" şeklinde bir yorum bulunmaktadır.

Farkın ne olduğunu merak ediyordum. İlki, küresel, anonim bir işlev bırakarak hafızayı alıyor mu? Parantez nerede bulunmalıdır?



İlgili: Anında işlev çağırma sözdizimi (JSLint olarak)
Bergi

1
Ayrıca bu yapının amacını okuyun veya bir ( teknik ) açıklamayı (ayrıca burada ) kontrol edin . Parantezlerin neden gerekli olduğunu öğrenmek için bu soruya bakın .
Bergi

Yanıtlar:


66

Neredeyse aynılar.

İlki, geçerli bir ifade yapmak için bir işlevin etrafına parantezler sarar ve onu çağırır. İfadenin sonucu tanımsız.

İkincisi işlevi çalıştırır ve otomatik çağrının etrafındaki parantezler onu geçerli bir ifade yapar. Ayrıca tanımsız olarak değerlendirilir.

İfadenin sonucu aynı olduğu için bunu yapmanın "doğru" bir yolu olduğunu sanmıyorum.

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"

8
JSLint "(function () {} ());" istiyor. JSLint, "Çağrıyı, işlevi içeren parantezlere taşı" diyor.
XP1

27
Aslında bu ikisiyle sınırlı değilsiniz, derleyicinin işlevin bir ifadenin parçası olduğunu ve +function(){}()veya gibi bir ifade olmadığını anlamasını sağlayan hemen hemen her şeyi kullanabilirsiniz !function(){}().
Tgr

49
@ XP1: JSLint , sağlam olmaktan çok Crockford'un tarzına özgü birçok şey istiyor . Bu onlardan biri.
TJ Crowder

@TJCrowder. Ne önerirsiniz? jQuery birinci stili, Crockford ise ikinci stili kullanır.
Teej

4
@ThorpeObazee: Gerçekten önemli değil, o yüzden ne istersen onu yap. I (daha outre olanlardan bazılarına karşı öneriyoruz -function(){}();, !function(){}();ve temelde hemen önce başka bir operatör functionde iş, ama parens kullanarak sürümleri devam ederdim). Önce bir bakın çok daha ikinciyi görmek daha ve benim tercihim; benim için de daha anlamlı, ama bu öznel. FWIW: jsbin.com/ejaqow
TJ Crowder

13

Bu durumda önemli değil. İlk tanımdaki bir işleve çözümlenen ve ikinci örnekte bir işlevi tanımlayan ve hemen çağıran bir ifade çağırıyorsunuz. Benzerler çünkü ilk örnekteki fonksiyon ifadesi sadece fonksiyon tanımıdır.

İşlevlere çözümlenen ifadeleri çağırmak için daha açık bir şekilde yararlı olan başka durumlar vardır:

(foo || bar)()

3
Diğer okuyuculara açıklık getirmek için (esas olarak ilk başta kendim anlamadığım için :)), foo ve / veya bar zaten bir işleve eşit olmalıdır. (örneğin, foo = function(){alert('hi');}hiçbiri işlev değilse, bir hata atılır.
Alexander Bird

3
@AlexanderBird Daha fazla açıklama - foo"Doğru" ise ancak bir işlev değilse de bir hata verecektir.
JLRishe

9

Sözdiziminin ötesinde herhangi bir fark yoktur.

Bunu yapmanın ikinci yöntemiyle ilgili endişelerinizle ilgili olarak:

Düşünmek:

(function namedfunc () { ... }())

namedfuncadı vermiş olmanıza rağmen yine de genel kapsamda olmayacaktır. Aynı şey anonim işlevler için de geçerli. Bu kapsamda almanın tek yolu, onu parens içindeki bir değişkene atamaktır.

((namedfunc = function namedfunc () { ... })())

Dış parantezler gereksizdir:

(namedfunc = function namedfunc () { ... })()

Ama yine de bu küresel bildirimi istemedin, değil mi?

Yani şu şekilde özetlenebilir:

(function namedfunc () { ... })()

Ve bunu daha da azaltabilirsiniz: asla kullanılmayacağı için isim gereksizdir (işleviniz özyinelemeli değilse ve o zaman bile kullanabilirsiniz arguments.callee)

(function () { ... })()

Düşünme şeklim bu (yanlış olabilir, henüz ECMAScript spesifikasyonunu okumadım). Umarım yardımcı olur.


Not arguments.calleeES5 beri kaldırılmış (ve sıkı modda yasak) olduğu.
nyuszika7h

"Dış parantezler gereksiz:" - Sanırım dosyalar birleştirildiğinde hataları önlerler, aksi takdirde bir! ya da başka birşey.
Jimmyt1988

-3

Douglas Crockford Fark, sadece mevcut gibi değil ilk stil IIFEs ! (seriuosly) Bu videoda da görebileceğiniz gibi !! .

Fazladan sarmalamanın (){her iki stilde} var olmasının tek nedeni, İşlev İfadesinin bu bölümünün yapılmasına yardımcı olmaktır , çünkü İşlev Bildirimi hemen çağrılamaz. Bazı komut / adil kullanım küçültmek-ERS +, !, -ve ~bunun yerine çok parantez. Bunun gibi:

+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();

Ve tüm bunlar alternatiflerinizle tamamen aynı. Bu durumlar arasından seçim yapmak tamamen size aittir ve hiçbir fark yaratmaz. { 1 Bayt büyük Dosya() üreten olanlar ;-)}

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.