Dlaczego wyniki różnią się w zależności od umiejscowienia aparatu ortodontycznego?

119

Dlaczego poniższe fragmenty kodu zaczerpnięte z tego artykułu dają różne wyniki z powodu tylko jednej zmiany w umiejscowieniu nawiasów klamrowych?

Gdy otwór nawias klamrowy {jest w nowej linii, test()powraca undefined, i „nie - złamał: niezdefiniowane” wyświetlany jest w pogotowiu.

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Kiedy nawias znajduje się w tym samym wierszu, co return, test()zwraca obiekt i ostrzega o „fantastycznym”.

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

JustLearn
źródło
semantyka półwstawiania po returnjest nieco inna niż w innych miejscach, a podział wiersza „oznacza więcej” w tym miejscu niż „w środku strumienia”.
dandavis

Odpowiedzi:

165

To jedna z pułapek JavaScript: automatyczne wstawianie średników. Wiersze, które nie kończą się średnikiem, ale mogą być końcem instrukcji, są automatycznie kończone, więc pierwszy przykład wygląda tak efektywnie:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

Zobacz także przewodnik po stylu JS Douglasa Crockforda , w którym wspomina się o wstawianiu średników.

W drugim przykładzie zwracasz obiekt (zbudowany za pomocą nawiasów klamrowych) z właściwością javascripti jej wartością "fantastic", w rzeczywistości taką samą jak ta:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
Pozostałość
źródło
5
Ciekawostka: w niektórych silnikach możesz skomentować automatycznie wstawiane średniki
Christopher Tarquini,
1
@ChrisT: Co? Które? Czy jest to gdzieś badane?
Sean McMillan
1
@SeanMcMillan Na pewno przeczytałem artykuły na ten temat, ale nie mogę znaleźć żadnego z nich na podstawie szybkiego wyszukiwania. Pamiętam, że wstawianie, return /*a następnie */{ skutecznie komentowałoby ukryty średnik w starszych wersjach Chrome. Nie jestem pewien, czy to nadal obowiązuje
Christopher Tarquini,
2
Z powodu tych dziwactw 10 lat temu obiecałem sobie: trzymać się z dala od sieci! Modliłem się, żeby Interweby zniknęły ... Niestety nie poszło zgodnie z planem i teraz też muszę walczyć z tymi problemami. Karma is ab * tch :)
Jowen
1
Widziałem ludzi, którzy religijnie sprzeciwiają się średnikom w JavaScript. Zawsze zastanawiałem się, co robią z tym dodatkowym czasem, który oszczędzają, nie umieszczając średników.
Iman Mohamadi,
9

Javascript nie wymaga średników na końcu instrukcji, ale wadą jest to, że musi odgadnąć, gdzie są średniki. W większości przypadków nie stanowi to problemu, ale czasami tworzy średnik w miejscu, w którym nie było to zamierzone.

Przykład z mojego wpisu na blogu na ten temat ( Javascript - prawie nie oparty na wierszach ):

Jeśli sformatujesz kod w ten sposób:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

Następnie jest interpretowany w następujący sposób:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

Instrukcja return przyjmuje postać bez parametrów, a argument staje się własną instrukcją.

To samo dzieje się z Twoim kodem. Funkcja jest interpretowana jako:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}
Guffa
źródło
3

Osobiście wolę styl Allman ze względu na czytelność (w porównaniu do stylu K&R).

Zamiast…

function test() {
  return {
    javascript : "fantastic"
  };
}

Podoba mi się…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

Ale to obejście. Ale mogę z tym żyć.

Michael R.
źródło
3
Myślę, że powinniśmy unikać osobistych preferencji, które odbiegają od głównego nurtu. Powinniśmy podążać za wyborami większości, co sprzyja spójności, co zwiększy czytelność
Jowen
1
Uważam, że jego kod jest bardziej czytelny niż K&R. Całkiem subiektywne, kiedy masz na myśli „czytelne”
Bran
Wolę też Allmana ... ale ze względu na ASI, kiedy muszę zwrócić obiekt, zostawiam półkę w tej samej linii co powrót. Wolę to niż dodać jedną linię "var x =" ...
Mik
1

Dzieje się tak, ponieważ javascript najczęściej umieszcza „;” na końcu każdej linii, więc po prostu, gdy masz return {w tej samej linii, silnik javascript widzi, że będzie coś więcej, a kiedy jest w nowej linii, myśli, że zapomniałeś wstawić ";", i umieszcza to za ciebie.

cichy
źródło
1
Nie rozumiem, dlaczego odpowiedzi Cichy'ego, Darina i Ivo zostały odrzucone?
BoltClock
1

Nawiasy klamrowe wskazują tutaj budowę nowego obiektu. Zatem twój kod jest równoważny z:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

który działa, a jeśli napiszesz:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

to już nie działa.

Darin Dimitrov
źródło
0

Problemem jest w istocie wstrzyknięcie średnika, jak opisano powyżej. Właśnie przeczytałem dobry wpis na blogu na ten temat. Wyjaśnia ten problem i wiele więcej na temat javascript. Zawiera również dobre referencje. Możesz to przeczytać tutaj

Ivo van der Wijk
źródło
Tak, również to przeczytałem, po przeczytaniu proszę tutaj o lepsze wyjaśnienie przez mistrza js.
JustLearn