¿Cómo difiere el manejo de saltos de línea de Python de los puntos y comas automáticos de JavaScript?

41

Javascript tiene una característica llamada Inserción automática de punto y coma, donde básicamente si el analizador encuentra un token inválido, y el último token antes de eso fue un salto de línea, entonces el analizador insertará un punto y coma donde está el salto de línea. Básicamente, esto le permite escribir todo su código JavaScript sin punto y coma, pero debe tener en cuenta algunos casos extremos, principalmente si tiene una palabra clave de retorno y luego el valor que desea devolver en una nueva línea.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Debido a estos problemas, hay docenas de artículos con títulos como 'La inserción automática de punto y coma es malo', 'Siempre use punto y coma en Javascript', etc.

Pero en Python nadie usa punto y coma y tiene exactamente los mismos trucos.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Funciona exactamente igual y, sin embargo, nadie tiene un miedo mortal al comportamiento de Pythons.

Creo que los casos en que el javascript se comporta mal son pocos como para poder evitarlos fácilmente. Retorno + valor en una nueva línea? ¿La gente realmente hace eso mucho?

Alguna opinión? ¿Usas punto y coma en javascript y por qué?

Einar Egilsson
fuente
3
No funciona exactamente igual. La inserción de punto y coma no va a donde sea que esté la nueva línea, necesariamente, en JavaScript. Vea el segundo ejemplo en esta página de Wikipedia . El punto y coma no se inserta donde está la nueva línea en ese ejemplo.
Reid
1
Mi punto no era que usar punto y coma y no usarlos funcionaba exactamente igual, el punto era que los casos extremos en javascript y python eran los mismos. Ciertamente, hay algunos casos extremos en los que debe saber qué está sucediendo. El mejor artículo que he leído sobre el tema: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson
44
Pongo punto y coma en JavaScript por la misma razón que uso puntos en oraciones. Claro, el intérprete generalmente puede entender sus declaraciones sin ellas, pero es simplemente una mala forma.
JD Isaacks
3
Puede considerar escribir Python válido en sus ejemplos. El indicador de comentario #no es `// '.
Aaron Dufour el
2
"explícito es siempre mejor que implícito"

Respuestas:

62

La razón es que en Python, las nuevas líneas son una forma inequívoca de separar las líneas de código; esto es por diseño, y la forma en que funciona ha sido cuidadosamente pensada. Como resultado, el código de Python es perfectamente legible y sin ambigüedades sin ningún marcador especial de final de declaración (aparte de la nueva línea).

Javascript, por otro lado, fue diseñado con una sintaxis tipo C en mente, donde las declaraciones siempre terminan con un punto y coma. Para que el lenguaje sea más tolerante a los errores, intenta adivinar dónde deben ir los puntos y comas adicionales para corregir el código. Dado que esto se ajustó en la sintaxis tipo C, no siempre funciona como se esperaba (a veces, el intérprete de guiones adivina mal) y puede generar un código bastante intuitivo.

O, argumentando en términos de "explícito es mejor que implícito": en Python, una nueva línea ya es completamente explícita, mientras que en Javascript es ambigua, por lo que agrega el punto y coma para hacerlo explícito.

tdammers
fuente
3
Ah, y puedes poner código en los comentarios usando comillas inversas.
tdammers
1
Un buen ejemplo de un caso en el que la inserción automática de punto y coma terminará haciendo cosas inesperadas es este: pastebin.com/aVeWGdya
HoLyVieR
55
En python, las reglas son bastante simples: las declaraciones terminan en saltos de línea a menos que haya una cadena de varias líneas no cerrada ("" ", '' '), un dict no cerrado ({}), una lista no cerrada ([]) o una barra invertida inmediatamente . antes del salto de línea en JavaScript, las reglas son mucho más complicadas.
Aaron Dufour
55
Cubrir el 99% de los errores es una buena manera de dejar atrás solo los realmente difíciles de encontrar. Está bien dejarlos atrás en Python porque hay reglas fáciles que cubren el 100% de los problemas.
Aaron Dufour el
1
@ Aaron: Olvidó "un conjunto de paréntesis no cerrado (())". (No es estrictamente "una tupla no cerrada" porque los paréntesis no solo se usan para las tuplas.)
JAB
28

Creo que hay una diferencia fundamental en la forma en que funciona en Python. Citando de la publicación Einar Egilsson vinculada a: "un punto y coma no está implícito al final de una línea si el primer token de la línea siguiente se puede analizar como parte de la misma declaración".

En Python, un salto de línea siempre finaliza la declaración, excepto en ciertos casos bastante obvios, como dentro de una expresión entre paréntesis. JavaScript, por otro lado, intentará analizar tantas líneas como sea posible antes de finalizar la declaración, lo que podría conducir a cosas como esta:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)
Henrik
fuente
8
Ahora aquí hay un giro divertido en este caso. Reemplace 14 con algo así (a + 1) ? do_something() : do_something_else();y, de repente, el área se establece en el valor de retorno de do_something()o do_something_else()y queda muy confundido.
Reid
20

A menudo minimizo mis archivos JS en modo de producción. Medios, eliminando comentarios y saltos de línea.

Sin el uso de punto y coma, eso rompería mi Javascript.

Deradon
fuente
8
OK, eso es valido. Pero si su minimizador es un analizador real, podría insertarlos nuevamente según sea necesario. O simplemente no elimine los saltos de línea, => mantiene los saltos de línea, pierde los puntos y comas, son aproximadamente el mismo número, por lo que no se pierde nada.
Einar Egilsson
2
@Einar Egilsson Closure Compiler de hecho hace esto.
seriousdev
1
En igualdad de condiciones, una nueva línea es el mismo número de bytes que un punto y coma. Su minimizador puede eliminar todas las líneas nuevas, pero luego requiere que haya punto y coma. Es un intercambio parejo.
Logan Bailey
3
@Logan: Eso suponiendo nuevas líneas de un byte, por supuesto ;-)
Cameron
1
Por supuesto, si utilizamos Python en lugar de Javascript, tendríamos que codificar WAY menos para hacer lo mismo, por lo que el hecho de que los punto y coma utilicen unos pocos bytes menos que la sangría es un punto discutible.
BlueRaja - Danny Pflughoeft
5

No funciona como lo describe usted.

Javascript tiene una característica llamada Inserción automática de punto y coma, donde básicamente si el analizador encuentra un token inválido, y el último token antes de eso fue un salto de línea, entonces el analizador insertará un punto y coma donde está el salto de línea.

Esto está mal. Ejemplo:

return
  1 + 2;

1es un token perfectamente válido, pero el analizador aún insertará un punto y coma directamente después return.

Como puede ver, incluso usted no puede decir exactamente dónde ocurrirá un punto y coma.

El problema con la inserción automática es doble:

  • Por un lado, las personas pueden dejar un punto y coma donde la inserción automática no puede determinar si es necesario insertarlo.
  • Además, un punto y coma podría insertarse donde no está previsto, como se indicó anteriormente.

Por supuesto, usar punto y coma después de cada declaración solo ayuda con la primera fuente de errores.

En cualquier caso, como puede suponer por ahora, creo que la inserción automática de punto y coma en sintaxis tipo C es una mala idea.

Svante
fuente
1
La especificación de secuencia de comandos de ECMA especifica explícitamente en qué casos se insertará un punto y coma, por lo que su línea "No se puede saber exactamente dónde ocurrirá un punto y coma" es incorrecta. El problema es que no es intuitivo en algunos casos, lo que hace que sea más difícil enseñar a alguien que no entiende cómo funciona.
zzzzBov
1
@zzzzBov: Sí, hay una especificación exacta, pero ¿alguien realmente tiene en cuenta todos los casos al codificar? ¿Estás seguro? Los programadores son flojos, y con razón; no quieren tener que recordar una regla complicada cuando una más simple lo haría. Entonces tratan de evitar tener que recordarlo.
Svante
Estoy de acuerdo en que la inserción de punto y coma es en gran medida innecesaria. Solo digo que hay una diferencia entre decir "no tienes idea de a dónde van los punto y coma" y "la especificación para la inserción del punto y coma es una mezcla poco intuitiva"
zzzzBov
1
@Svante: Pero el ejemplo de devolución nos muestra que tenemos que conocer estas reglas de todos modos. Allí usaste un punto y coma, pero no te ayudó a hacer lo que querías. Entonces, dado que el lenguaje tiene esta característica, tenemos la opción de (1) Escribir puntos y comas en todas partes y conocer las reglas para que entendamos lo que sucederá (2) No escribir puntos y comas en todas partes, y entender las reglas para entender lo que sucederá. Dada esa opción, creo que preferiría saltear los puntos
Einar Egilsson
4

Declararía una razón simple:

Javascript se ve "un poco java-ish" o "un poco C-ish". Por supuesto, es un lenguaje dinámico, por lo que se ve diferente ... pero acéptelo: hay llaves. Los idiomas con llaves generalmente tienen punto y coma. Los reflejos naturales entran en acción y hacen que tu dedo vaya hacia la tecla de punto y coma antes de golpear Enter.

Python, por el contrario, incluso de un vistazo se ve totalmente diferente. Por lo tanto, se forma intuitivamente poca o ninguna analogía con "los lenguajes aburridos estándar" y cuando uno ingresa al "modo pitón", la falta de punto y coma es algo natural.

Kos
fuente
2

Existen varias buenas razones para no utilizar la inserción de punto y coma en JavaScript.

Principalmente es porque la inserción de punto y coma como se define en el estándar ECMAScript no es intuitiva para algunos casos. @Svante señala un caso en el returnque el uso de la nueva línea causará problemas.

Lo que él no menciona es que causará problemas si también usa punto y coma, porque la inserción de punto y coma ocurre ya sea que lo desee o no.

Otra muy buena razón para no utilizar la inserción de punto y coma es el control de salida. En muchos casos, JavaScript se ejecuta a través de un minificador antes de usarse en producción. Algunos minificadores pueden manejar casos de inserción automática de punto y coma, pero no veo ninguna razón para confiar en que funcione perfectamente

Además, para los sistemas de gestión de contenido, JavaScript en línea puede minimizarse automáticamente, y he visto una serie de casos en los que el minimizador simplemente elimina los comentarios y recorta los espacios en blanco (incluidas las nuevas líneas) desde el principio y el final de cada línea.

Para los autores que no tienen la opción de elegir qué herramientas se eligen, es mucho más fácil seguir un formato que funcione en la gran mayoría de los casos.

zzzzBov
fuente
Ah, lo siento, pero con respecto a su tercer párrafo, lo menciono en mi penúltima oración. :)
Svante
Sí, el problema de las herramientas es válido (aunque los buenos minificadores deberían manejar esto, por ejemplo, el compilador de cierre). Pero en mi opinión, necesitamos conocer estas reglas de todos modos, para evitar cosas como el ejemplo de 'retorno'. Y una vez que conozca las reglas, también podría usar la función, especialmente porque hace que el código (IMO) sea más legible.
Einar Egilsson
1

No usar punto y coma es una receta para fallar cuando minimizas tus archivos JavaScript. Por eso le tengo miedo.

Monje oriental
fuente
1

En Javascript, puede escribir un programa que sería sintácticamente correcto en ausencia de una inserción automática de punto y coma, y ​​ASI transformará ese programa en un programa sintácticamente correcto diferente (por ejemplo, transformando el código que devuelve un valor en un código que no devuelve nada). No hay caso análogo en Python. En Python ningún salto de línea que puede acabar con una declaración será terminar un comunicado, a menos que se escapó con una barra invertida. Técnicamente, supongo que las reglas de Javascript son igualmente deterministas, pero no sé si podría resumir las reglas de Javascript para terminar las declaraciones en una sola oración.

Ryan C. Thompson
fuente
1

En la mayoría de los casos, el ASI de JavaScript maneja las cosas como se esperaba. Un ejemplo de ASI que tal vez no se comporta de la manera que cabría esperar es este:

var i = 0

(function() {
   // do something
})()

Esto se interpretará como llamar a la función 0con la función anónima y luego ejecutar el resultado. En este caso, probablemente quería hacer una tarea, luego ejecutar inmediatamente la función anónima.

Para alguien que no esté familiarizado con ASI, puede ser muy confuso cuando se encuentra con problemas como este, por lo que siempre recomiendo a los desarrolladores de mi equipo que utilicen punto y coma.

(Como comentario aparte: no uso punto y coma cuando trabajo en proyectos personales / secundarios porque sé que nadie más necesitaría mantener el código).

jay_soo
fuente
1

Como tú, creo que es un poco paranoico. Las reglas para la inserción de punto y coma están bien definidas en JavaScript, al igual que en Python y CoffeeScript. Nadie ensucia Python o CoffeeScript con punto y coma, entonces, ¿por qué se trata JavaScript de manera diferente?

Creo que es una reacción exagerada al miserable estado del código JavaScript típico de hace unos diez años: JavaScript se consideraba un lenguaje débil, con errores, feo, inútil. Fue una vergüenza. ¡No podrías escribir un buen código en JavaScript!

Luego, la gente vino y trató de demostrar que podía escribir un código hermoso y claro en JavaScript. La regla de " siempre usar punto y coma" era parte de esta ola. Y para ser sincero, puede aclarar algunas situaciones un poco.

¿Por qué JavaScript todavía se trata de manera diferente?

Hay inercia Y no debe pasarse por alto que las personas que aprecian el código explícitamente estructurado a menudo prefieren los lenguajes de estilo C. Las personas que aprecian el código implícitamente estructurado a menudo pasan a lenguajes que no son de estilo C (como CoffeeScript).

Cierre vaquero
fuente
0

Los uso en Javascript estrictamente por coherencia. Si la mayoría de las líneas tienen

Python los tiene para casos extremos como declaraciones múltiples en una sola línea, javascript los tiene y dado que los encontrará utilizados regularmente, me ajusto a la norma donde se usan.

No puedo encontrar un uso para múltiples declaraciones en la misma línea y, por lo tanto, no preveo el uso de punto y coma.

Chris
fuente
Sí, he arreglado el ejemplo de Python. Pero el punto sigue siendo, Python también tiene punto y coma, puedes ponerlos después de cada declaración (y debes hacerlo si tienes más de uno en cada línea) pero la gente no los usa.
Einar Egilsson
0

Si usa algo como bundle-fu y administrador de activos para su aplicación web en rieles, entonces se rompería horriblemente si no encuentra un punto y coma al final del token en javascript. Por lo tanto, es una buena práctica poner uno.

tranquilo
fuente
Bueno, los tres grandes, YUI Compressor, Closure Compiler y UglifyJS, todos hacen inserción de punto y coma. No me sorprende que el puerto rubí de JSMin tenga problemas.
Benjamin Atkin
0

No recuerdo qué versión exacta de IE, pero hay algunos casos en los que IE literalmente fallará si falta un punto y coma. IIRC es cuando tienes en el ámbito global algo como:

var myFunc = function() {
  ...
}

Si no agrega el; después de la llave de cierre, el programa realmente fallará en algunas versiones de IE. Eso, junto con las otras razones (incluida la recomendación de Crockford de usarlas siempre explícitamente) me ha llevado a usarlas siempre explícitamente en todos los casos.

apinstein
fuente