JavaScript dışında herhangi bir dil ayraç başlangıç ​​konumları arasında (aynı satır ve sonraki satır) arasında bir fark var mı?


91

Bugün, O'Reilly'nin JavaScript modellerini rastgele okurken ilginç bir şey buldum (referans için sayfa 27).

Javascript'te, bazı durumlarda, küme ayracı başlangıç ​​konumunun farklı olması durumunda bir fark vardır.

function test_function1() {
    return
    {
        name: 'rajat'
    };
}

var obj = test_function1();
alert(obj);  //Shows "undefined"

Süre

function test_function2() {
    return {
        name: 'rajat'
    };
}

var obj = test_function2();
alert(obj); //Shows object

JSfiddle Demosu

Dışarıda başka bir dilin böyle bir davranışı var mı? Öyleyse, alışkanlığımı kesinlikle değiştirmem gerekir .. :)

Esas olarak PHP, C, C ++, Java ve Ruby hakkında endişeliyim.


1
Chrome ve IE9'da yeniden üretildi, iyi yakalama: P
gideon

4
Beyaz boşluk duyarlılığı çalışmak için yapılabilir - python veya çizgi moduna fortran bakın - ancak ince beyaz boşluk duyarlılığı şeytanın işidir. Gah! Bu yapmak kadar kötü!
dmckee --- eski moderatör kedicik

Bu etkileyici! Güzel bul!
CheckRaise

Şimdi javascript'in neden bu şekilde davrandığını bilmek istiyorum.
CheckRaise

4
@CheckRaise: Kuralları burada özetliyorum
Eric Lippert

Yanıtlar:


53

İfadeleri sınırlandırmak için noktalı virgüllere (ancak bunun yerine yeni satırlara) güvenmeyen herhangi bir dil buna izin verir. Python'u düşünün :

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}

Visual Basic'te benzer bir durum oluşturabilirsin ama kafamın tepesinden baktığımda nasıl olduğunu anlayamıyorum çünkü VB değerlerin nereye yerleştirilebileceği konusunda oldukça kısıtlayıcı. Ancak statik analizör erişilemez koddan şikayet etmedikçe aşağıdakiler çalışmalıdır:

Try
    Throw New Exception()
Catch ex As Exception
    Throw ex.GetBaseException()
End Try

' versus

Try
    Throw New Exception()
Catch ex As Exception
    Throw
    ex.GetBaseException()
End Try

Bahsettiğin dillerden Ruby aynı özelliğe sahiptir. PHP, C, C ++ ve Java yalnızca satırsonu boşluk olarak atıldıkları ve ifadeleri sınırlamak için noktalı virgül gerektirdikleri için değil.

Ruby'deki Python örneğindeki eşdeğer kod:

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil

2
VB örneğiniz, "_" satır devam dizisini kullanmadığınız sürece, VB hiçbir zaman bir ifadenin birden fazla satıra yayılmasına izin vermediğinden, bunu pek anlamaz .
phoog

2
Tamam, önceki yorumu geri çekiyorum çünkü spesifikasyona baktım, VB.NET'in örtük satır sürdürmelerini desteklediği bazı bağlamlar var. Herhangi bir deneyimli VB programcısının bu örneği bir "yakaladım" olarak değerlendireceğinden şüpheliyim, çünkü bu oldukça açık Throwve ex.GetBaseException()ayrı mantıksal satırlar. Daha spesifik olarak, Basic tarihsel olarak ifadelerini sınırlandırmak için satırları kullandığından, bir "yakalama", bir programcının yeni bir mantıksal satırda yeni bir ifade oluşturduğunu düşündüğü, ancak yapmadığı bir durum olabilir.
phoog

@phoog Doğru, kesinlikle bir gotcha değil.
Konrad Rudolph

40

JavaScript yorumlayıcısı, bir ;tane bulamazsa her satırın sonuna otomatik olarak bir ekler (bazı istisnalar dışında, buraya girmeden :).

Yani temelde sorun, parantezlerin konumu değil (burada bir nesneyi temsil eder, çoğu dilde olduğu gibi bir kod bloğu değildir), ancak ilk örneğinizi return ;=> 'a zorlayan bu küçük "özellik" dir undefined. return ES5 spesifikasyonundaki davranışını kontrol edebilirsiniz .

Benzer davranışa sahip diğer diller için Konrad'ın cevabına bakın .


5
Çok olumlu oy alan cevap, ama aslında yanlış, üzgünüm. Açıklama güzel ama lütfen hatayı düzeltin.
Konrad Rudolph

JavaScript ile ilgili kısım yanlış değildir, onun yaptığı gibi davranma şekli, undefineddöndürülmeye zorlayan noktalı virgül eklemesidir . Ben öneki diğer diller hakkında biraz yazdım afaik yüzden inanmayarak :) beraberinizde götürün.
Alex Ciminian

5
Ancak JS'nin "bazı istisnalar dışında" her satırın sonuna "" noktalı virgül "eklediği doğru değildir; daha doğrusu, genellikle gelmez bir noktalı virgül yerleştirin ve bu sadece birkaç durum vardır yapar . Bu yüzden bu kadar çok soruna neden oluyor.
ruakh

26

Kesinlikle. Google'ın go programlama dili çok benzer bir davranış sergiliyor (farklı efektlerle de olsa). Orada açıklandığı gibi:

Aslında, C veya Java'da olduğu gibi biçimsel dil noktalı virgül kullanır, ancak bunlar bir ifadenin sonu gibi görünen her satırın sonuna otomatik olarak eklenir. Bunları kendiniz yazmanıza gerek yok.

..snip ...

Bu yaklaşım, temiz görünümlü, noktalı virgül içermeyen kod sağlar. Bir sürpriz, if ifadesi gibi bir yapının açılış parantezini if ​​ifadesiyle aynı satıra koymanın önemli olmasıdır; yapmazsanız, derlenemeyebilecek veya yanlış sonuç verebilecek durumlar vardır. Dil, küme ayracı stilini bir dereceye kadar zorlar.

Gizlice, sanırım Rob Pike, One True Brace Style'a ihtiyaç duymak için bir bahane istedi.


10
Harika, bunu bilmiyordum :). Kişisel olarak, otomatik noktalı virgül eklemenin iyi bir fikir olduğunu düşünmüyorum. Dil konusunda deneyimsiz insanların anlamakta zorlanacağı ince hatalar ortaya çıkarabilir. Noktalı virgül içermeyen kod yazmak istiyorsanız, python yolunu tercih ederim.
Alex Ciminian

Olmadan @Alex diller bile herhangi noktalı virgül (VB) bu özelliği var. Ve görünüşe göre tercih ettiğiniz Python da, bunu JavaScript ile aynı şekilde ele alsa bile.
Konrad Rudolph

Olumlu oy verirdim, ancak ikinci cümlenin o kadar tamamen yanlış ki, olumsuz oy kullanmak istememe neden oluyor. Sanırım iptal ediyorlar. ;-)
ruakh

1
@ruakh "tam olarak bunu yapıyor" mu demek istiyorsun yoksa rob pike hakkındaki şakadan mı bahsediyorsun? İlk durumda, "gitmek aynı davranışı sergiler" şeklinde yeniden ifade edebilirdim, ikincisinde, kötü mizah anlayışım rahatsız ederse özür dilerim;)
Dave

1
Demek istediğim, "Git tam olarak bunu yapar." Go'nun noktalı virgül ekleme için orijinal önerisi, açıkça JavaScript'inkiyle tezat oluşturarak, "Bu teklif size JavaScript'in isteğe bağlı noktalı virgül kuralını hatırlatabilir, bu da aslında ayrıştırma hatalarını düzeltmek için noktalı virgül ekler. Go önerisi son derece farklıdır" ve bu, her düzeyde oldukça doğru: farklı çalışıyor, farklı etkileri var ve neredeyse hiç etkisi yok. (Her ne kadar sinir bozucu olsa da, tüm Go kodunda tutarlı bir gereklilik olduğu için
OTBS

14

Bu sorunun cevabı oldukça kolaydır. "Otomatik noktalı virgül ekleme" olan herhangi bir dil, bu satırda sorun yaşayabilir. Bununla ilgili problem

return
{
     name: 'rajat'
};

..js motorunun return;ifadeden sonra noktalı virgül ekleyeceğidir (ve bu nedenle, geri döner undefined). Bu örnek, kıvrımlı parantezleri her zaman sağ tarafta ve asla sol tarafta açmak için iyi bir nedendir . Zaten doğru bir şekilde fark ettiğiniz için, aynı satırda kıvrımlı bir parantez varsa, yorumlayıcı bunu fark edecek ve bir noktalı virgül ekleyemeyecektir.


6

FWIW, JSLint bu sözdizimiyle birkaç uyarı bildirir:

$ jslint -stdin
function foo(){
  return
  { x: "y" };
}
^D
(3): lint warning: unexpected end of line; it is ambiguous whether these lines are part of the same statement
  return
........^

(3): lint warning: missing semicolon
  { x: "y" };
..^

(3): lint warning: unreachable code
  { x: "y" };
..^

(3): lint warning: meaningless block; curly braces have no impact
  { x: "y" };
..^

(3): lint warning: use of label
  { x: "y" };
.....^

(3): lint warning: missing semicolon
  { x: "y" };
...........^

(3): lint warning: empty statement or extra semicolon
  { x: "y" };
............^


0 error(s), 7 warning(s)

1

Bununla karşılaştığım ilk dil awk idi (aynı zamanda sözdizimi "tuhaflıkları" payına sahiptir; isteğe bağlı noktalı virgül, yalnızca beyaz boşluk kullanan dize birleştirme vb.) Sanırım D sözdizimini gevşek bir şekilde temel alan DTrace tasarımcıları awk üzerinde, bu özellikleri kopyalamayacak kadar mantıklıydım, ama aklımın ucunda hatırlayamıyorum. Basit bir örnek (Mac'imden bir DTD'deki ENTITY etiketlerinin sayısını sayarak):

$ cat printEntities.awk 
# This prints all lines where the string ENTITY occurs
/ENTITY/ {
  print $0
}
$ awk -f printEntities.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     119

Bunun yerine bu küçük komut dosyası kendi başına bir satırda küme ayracı ile yazılsaydı, şu olurdu:

$ cat printAll.awk 
# Because of the brace placement, the print statement will be executed
# for all lines in the input file
# Lines containing the string ENTITY will be printed twice,
# because print is the default action, if no other action is specified
/ENTITY/
{ 
   print $0 
}
$ awk -f printAll.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     603
$ /bin/cat < /usr/share/texinfo/texinfo.dtd | wc -l
     484
$ 
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.