91

Hoy, mientras estaba leyendo aleatoriamente los patrones de JavaScript del libro de O'Reilly, encontré una cosa interesante (página 27 para referencia).¿Hay algún otro idioma que no sea JavaScript que tenga una diferencia entre las ubicaciones de inicio de llaves (la misma línea y la siguiente)?

En Javascript, en algunos casos, existe una diferencia si la ubicación de inicio de la llave es diferente.

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

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

Mientras

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

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

JSfiddle Demo

¿Hay alguna otra lengua por ahí tiene este tipo de comportamiento? Si es así, entonces tendría que cambiar mi hábito con seguridad ... :)

Me preocupan principalmente PHP, C, C++, Java y ruby.

+1

Reproducido en Chrome e IE9, buena captura: P – gideon

+4

sensibilidad el espacio en blanco se puede hacer para trabajar --- vistazo a pitón o el modo de línea de FORTRAN --- pero sutil * * sensibilidad espacio en blanco es el trabajo de la diablo. Gah! ¡Esto es tan malo como hacer! – dmckee

+0

¡Esto es impresionante! Buen hallazgo! – CheckRaise

Respuesta

53

Cualquier lenguaje que no dependa de punto y coma (pero en cambio en líneas nuevas) para delimitar las declaraciones potencialmente lo permite. Considere Python:

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

Usted puede ser capaz de construir un caso similar en Visual Basic pero fuera de la parte superior de mi cabeza no puedo encontrar la manera de VB porque es bastante restrictivo en donde los valores pueden ser metido. Sin embargo, el siguiente debería funcionar, a menos que el analizador estático se queja sobre el código inalcanzable:

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 

De las lenguas que usted ha mencionado, Rubí tiene la misma propiedad. PHP, C, C++ y Java no simplemente porque descartan la nueva línea como espacios en blanco, y requieren punto y coma para delimitar las declaraciones.

Aquí está el código equivalente a partir del ejemplo de Python en Ruby:

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

Su ejemplo de VB no es suficiente porque VB * nunca * permite que una instrucción abarque varias líneas a menos que use la secuencia de continuación de línea "_". – phoog

+2

Ok, retraigo el comentario anterior porque acabo de ver las especificaciones, hay algunos contextos en los que VB.NET admite continuidades de línea implícitas. Sin embargo, dudo que ningún programador experimentado de VB considere este ejemplo como "gotcha", ya que es bastante obvio que 'Throw' y' ex.GetBaseException() 'son líneas lógicas separadas. Más específicamente, dado que Basic históricamente usa líneas para delimitar sus declaraciones, un "gotcha" sería una situación donde un programador cree que ha creado una nueva declaración en una nueva línea lógica, pero no lo ha hecho. – phoog

+0

@phoog Cierto, definitivamente no es una mierda. –

40

El intérprete de JavaScript agrega automáticamente un ; al final de cada línea si no encuentra uno (con algunas excepciones, no entrar en ellos aquí :).

Así que, básicamente, el problema no es la ubicación de las llaves (que en este caso representa un objeto literal, no es un bloque de código, como en la mayoría de los idiomas), pero esta pequeña 'característica' que obliga a su primer ejemplo de return ; =>undefined. Puede verificar el comportamiento de returnin the ES5 spec.

Para otros idiomas que tienen un comportamiento similar, consulte Konrad's answer.

+5

Respuesta muy votada, pero en realidad es incorrecta, lo siento. La explicación es buena, pero por favor corrige el error. –

+0

La parte sobre JavaScript no está mal, la forma en que se comporta como lo hace es debido a la inserción de punto y coma que obliga a devolver 'undefined'. Escribí un poco sobre los otros idiomas con el prefijo _afaik_, así que tómalo con un poco de sal :). –

+5

Pero no es cierto que JS inserta un punto y coma "al final de cada línea" "con algunas excepciones"; más bien, generalmente * no * inserta un punto y coma, y ​​solo hay unos pocos casos donde * lo hace *. Es por eso que causa tantos errores. – ruakh

14

La respuesta a esa pregunta es bastante sencilla. Cualquier lenguaje que tenga "inserción automática de punto y coma" podría tener problemas en esa línea. El problema con este

return 
{ 
    name: 'rajat' 
}; 

..es que el motor js insertará un punto y coma después de la declaración return; (y por lo tanto, volver undefined). Este ejemplo es una buena razón para abrir las llaves siempre en el lado derecho y nunca en el lado izquierdo también. Como ya ha notado correctamente, si hay un corchete en la misma línea, el intérprete lo notará y no podrá insertar un punto y coma.

26

Lo más seguro. El lenguaje de programación go de Google muestra un comportamiento muy similar (aunque con diferentes efectos). Como se explica allí:

De hecho, lo que ocurre es que el lenguaje formal usa punto y coma, como en C o Java, pero se insertan automáticamente al final de cada línea que parece el final de una instrucción. No necesita escribirlos usted mismo.

..snip ...

Este enfoque hace que para el código de aspecto limpio y sin punto y coma. La única sorpresa es que es importante colocar la llave de apertura de una construcción como una instrucción if en la misma línea que si; si no lo hace, hay situaciones que pueden no compilarse o dar el resultado incorrecto. El lenguaje fuerza el estilo de refuerzo hasta cierto punto.

En secreto, creo que Rob Pike solo quería una excusa para necesitar el estilo de One True Brace.

+10

Genial, no sabía de esto :). Personalmente, no creo que la inserción automática de punto y coma sea una buena idea. Puede introducir errores sutiles que las personas inexpertas con el idioma tendrán dificultades para descubrir. Si quiere escribir código libre de punto y coma, prefiero el modo python. –

+0

@Alex Incluso los idiomas sin * cualquier punto y coma (VB) tienen esta propiedad. Y también lo hace Python, que aparentemente prefiere, aunque maneja esto de forma idéntica a JavaScript. –

+0

He votado positivamente, excepto que su segunda oración es tan completamente errónea que me hace querer rechazarla. Supongo que se cancelan.;-) – ruakh

6

Fwiw, JSLint informes de varias advertencias con que la sintaxis:

$ 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

La primera lengua, donde me encontré con este era awk (que también tiene su parte de sintaxis "rarezas"; semi-puntos opcionales, concatenación de cadenas usando solo espacios en blanco y así sucesivamente ...) Creo que los diseñadores de DTrace, que basaron la sintaxis D en awk, tenían suficiente sentido como para NO copiarlos e características, pero no puedo recordar de la parte superior de mi cabeza. Un ejemplo sencillo (contando el número de etiquetas de entidad en una DTD, desde mi Mac):

$ 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 

Si este pequeño script en su lugar fueron escritos con el aparato ortopédico en una línea propia, esto es lo que sucedería:

$ 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 
$ 
Cuestiones relacionadas