Dzisiaj, kiedy losowo czytałem książkę O'Reilly o wzorach JavaScript, znalazłem jedną interesującą rzecz (strona 27 w celach informacyjnych).
W JavaScript w niektórych przypadkach istnieje różnica, jeśli lokalizacja początkowa nawiasów klamrowych jest inna.
function test_function1() {
return
{
name: 'rajat'
};
}
var obj = test_function1();
alert(obj); //Shows "undefined"
Podczas
function test_function2() {
return {
name: 'rajat'
};
}
var obj = test_function2();
alert(obj); //Shows object
Czy jakikolwiek inny język ma takie zachowanie? Jeśli tak, to na pewno musiałbym zmienić nawyk .. :)
Martwię się głównie o PHP, C, C ++, Javę i Ruby.
javascript
language-agnostic
programming-languages
language-design
Rajat Singhal
źródło
źródło
Odpowiedzi:
Każdy język, który nie opiera się na średnikach (ale zamiast na nowych wierszach) do oddzielania instrukcji, potencjalnie na to pozwala. Rozważmy Pythona :
>>> def foo(): ... return ... { 1: 2 } ... >>> def bar(): ... return { 1: 2 } ... >>> foo() >>> bar() {1: 2}
Być może uda ci się skonstruować podobny przypadek w Visual Basic, ale nie wiem, jak to zrobić, ponieważ VB jest dość restrykcyjny w miejscach, w których można umieszczać wartości. Ale poniższe powinny zadziałać, chyba że analizator statyczny narzeka na nieosiągalny kod:
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
Z wymienionych języków Ruby ma tę samą właściwość. PHP, C, C ++ i Java nie tylko dlatego, że odrzucają znak nowej linii jako biały znak i wymagają średników do oddzielania instrukcji.
Oto odpowiednik kodu z przykładu Pythona w Rubim:
>> def foo >> return { 1 => 2 } >> end => nil >> def bar >> return >> { 1 => 2 } >> end => nil >> foo => {1=>2} >> bar => nil
źródło
Throw
iex.GetBaseException()
są to oddzielne linie logiczne. Mówiąc dokładniej, ponieważ Basic historycznie używa linii do rozgraniczenia swoich instrukcji, „gotcha” byłaby bardziej prawdopodobna w sytuacji, w której programista sądzi, że utworzył nową instrukcję w nowej linii logicznej, ale tego nie zrobił.Interpreter JavaScript automatycznie dodaje znak
;
na końcu każdego wiersza, jeśli go nie znajdzie (z pewnymi wyjątkami, nie wchodząc w to tutaj :).Zasadniczo więc problemem nie jest lokalizacja nawiasów klamrowych (które tutaj reprezentują literał obiektu, a nie blok kodu, jak w większości języków), ale ta mała „funkcja”, która wymusza na pierwszym przykładzie
return ;
=>undefined
. Możesz sprawdzić zachowaniereturn
w specyfikacji ES5 .W przypadku innych języków, które mają podobne zachowanie, sprawdź odpowiedź Konrada .
źródło
undefined
zwrócenie. Napisałem trochę o innych językach z prefiksem afaik , więc weź to z przymrużeniem oka :).Z całą pewnością. Język programowania go Google wykazuje bardzo podobne zachowanie (aczkolwiek z różnymi efektami). Jak tam wyjaśniono:
Potajemnie, myślę, że Rob Pike chciał tylko wymówki, by wymagać stylu One True Brace.
źródło
Odpowiedź na to pytanie jest dość prosta. Każdy język, w którym zastosowano „automatyczne wstawianie średnika”, może mieć problemy w tym wierszu. Problem z tym
return { name: 'rajat' };
.. polega na tym, że aparat js wstawi średnik po
return;
instrukcji (a tym samym zwróciundefined
). Ten przykład jest dobrym powodem, aby otwierać nawiasy klamrowe zawsze po prawej stronie, a nigdy również po lewej stronie. Ponieważ już poprawnie zauważyłeś, jeśli w tym samym wierszu znajduje się nawias klamrowy, tłumacz zauważy to i nie może wstawić średnika.źródło
FWIW, JSLint zgłasza kilka ostrzeżeń o następującej składni:
$ 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)
źródło
Pierwszym językiem, w którym się z tym spotkałem, był awk (który również ma swój udział w "osobliwościach" składniowych; opcjonalne średniki, konkatenacja ciągów przy użyciu tylko białych znaków i tak dalej ...) Myślę, że projektanci DTrace, którzy opierali składnię D luźno w awk, miałem dość rozsądku, aby NIE kopiować tych funkcji, ale nie pamiętam od początku mojej głowy. Prosty przykład (liczenie liczby tagów ENTITY w DTD, z mojego Maca):
$ 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
Gdyby zamiast tego ten mały skrypt został napisany z nawiasem klamrowym w osobnym wierszu, tak by się stało:
$ 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 $
źródło