2010-09-26 24 views
8

JavaScript'te bir işlevi tanımlamanın birkaç yolu olduğunu biliyorum. En yaygın olanları ikisi şunlardır:"Geleneksel" C stili işlev bildirimini kullandığımda JavaScript'te neler oluyor?

(1) function add (a, b) { 
     return a + b; 
    } 

(2) var add = function (a, b) { 
     return a + b; 
    } 

Ben tıpkı diğer değişkenler gibi etrafında geçirilebilir bir nesne olarak bir fonksiyonun fikri ile rahatım. Yani (2)'un ne yaptığını mükemmel anlıyorum. Bir işlev yaratıyor ve add'a atayım (bunun global kapsamda olduğunu söyleyelim, yani add global bir değişkendir). Ama bunun yerine (1) kullanıyorsam ne oluyor? Zaten yürütme sırasına göre bir fark yarattığını zaten biliyorum:kullanırsam add()'un tanımlandığı koddaki noktadan önce add()'a başvurabilirim, ancak (2) kullanıyorum, sonra da işlevimi add adresine atayabilirim. add()'a başvurmaya başlayabilirsiniz.

için bir kısayol olabilir, ancak diğer C stili diller gibi davranıp davranmadığı bir işlev tanımlamamıza izin veren bir kısayol olabilir mi? Yoksa dahili olarak farklı bir işlev türü midir? Hangi daha fazla "JavaScript'in ruhu" (eğer bu bir terim çok belirsiz ise)? Kendinizi bir diğeriyle sınırlar mısınız, eğer öyleyse hangisi?

cevap

6

O zaten function declarations temel özelliklerinden farkında gibi görünüyor (1) ve function expressions (2). Ayrıca (1) hala bir işlev değer içeren add adlı bir yerel değişken vardır sadece beğendiğiniz dikkat (2):

function hello() { 
    alert('Hello World'); 
} 

console.log(typeof hello); // prints "function" 

setTimeout(hello, 1000); // you can still pass functions around as arguments, 
          // even when using function declarations. 

kayda değer bir diğer nokta olduğunu işlev bildirimleri (1) olmamalı' İşlevsel olarak (örneğin, if ifadelerinde olduğu gibi) tanımlamak için kullanıldığından, belirttiğiniz gibi, bunlar otomatik olarak JavaScript kapsamındaki yorumlayıcıyı içeren kapsamın üst kısmına taşınır. Bu normal olarak hoisting olarak adlandırılır.

JavaScript'in yaklaşımında hangi yaklaşımın daha fazla olduğu gibi, işlev ifadelerini (2) kullanmayı tercih ediyorum. Daha güvenilir bir görüş için, Douglas Crockford, popüler The Good Parts book 'daki "Kötü Parçalar" bölümünde işlev bildirimlerini (1) listeler.


Ayrıca işlev ifadeleri (aşağıda @Tim Down's yorumları gör) olarak da bilinir.
Aslında bazı tarayıcılarda işlev bildirimleriif ifadelerinde (yine aşağıdaki yorumlara bakın) işlem yapılabilir.
JavaScript: The Good Parts - Ek B: Sayfa 113.

+2

ECMAScript teknik özelliklerine göre 'if' ifadesi bloğu içinde bir işlev bildirimi bir sözdizimi hatasıdır. Büyük tarayıcıların hiçbiri, IE ve Mozilla tarafından ayarlanan emsallerden dolayı hata yapmıyor. Mozilla ECMAScript'e bir uzantı içerecek şekilde çepeçevre alır (http://www.jibbering.com/faq/#functionStatement, http://kangax.github.com/nfe/#function-statements) bir 'FunctionStatement' adı. JScript, spekülasyona daha az saygı duyar ve Tanrı-bilir-ne içseldir. –

+1

Düzenlemenize bir yorum: fonksiyon tanımlamaları da yanlış işlev ifadeleri olarak anılacaktır, ancak olduğu doğrudur. (Önceki açıklamada bağlantılı) comp.lang.javascript SSS çok ikna edici bu noktayı yapar: * "terimi fonksiyon ifadesi yaygın ve yanlış çünkü ECMAScript'teki bir' FunctionDeclaration yanıltıcı bir 'FunctionDeclaration'.This tanımlamak için kullanılmıştır 'a Statement' değildir; orada' Statement' izin verilen bir programda yerler vardır ama bir 'FunctionDeclaration' değil" * –

+0

@Tim: ilginç yorumlar için teşekkürler.. Sorunu adlandırma "ifadesi" farkında değildi. –

2
function foo() {}; 
foo.toString() //-> "function foo() {}" 

var bar = foo; 
bar.toString() //-> "function foo() {}" 

Yani adlandırılmış işlevini bildirir. Değişken ne olursa olsun, adı korunur.Diğer sözdizimini kullanmak anonim bir işlevdir, adsızdır ve yalnızca bir değişken tarafından başvuruda bulunularak erişilebilir.

var foo = function() {}; 
foo.toString() //-> "function() {}" 

var bar = foo; 
bar.toString() //-> "function() {}" 

Hangi stilde kullanılacağı konusunda büyük bir kural yoktur. Anonim sözdizimini kişisel olarak desteklesem de bana, işlevlerin gerçekten de etrafından geçirilebilecek nesneler olduğunu hatırlatıyor. Aynı zamanda, işlevlerin bu şekilde bildirilmesini gerektiren “hepsi büyük bir ana nesne” yaklaşımını tercih etme eğilimindeyim.

var MyThingy = { 
    foo: function() { alert('foo') }, 
    bar: function() { MyThingy.foo() } 
} 

Ancak işlevler oluşturulduktan sonra, farklılıklar gerçekten önemli değildir ve aynı şekilde davranır. Ancak anonim sözdizimi, bahsettiğiniz ileriye dönük tarama sihrinden daha az, karmaşık kodda ve tekdüzen kapsam belirleme durumlarında daha az hata var.