¿Por qué los resultados varían según la colocación de las llaves?

119

¿Por qué los siguientes fragmentos de código, extraídos de este artículo , producen resultados diferentes debido a un solo cambio en la ubicación de las llaves?

Cuando la llave de apertura {está en una nueva línea, test()regresa undefinedy "no - se rompió: indefinido" se muestra en la alerta.

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);
}

Cuando la llave está en la misma línea que return, test()devuelve un objeto y se alerta "fantástico".

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);
}

Solo aprende
fuente
la semántica de semiinserción posterior returnes ligeramente diferente a la de otros lugares, y un salto de línea "significa más" en ese lugar de lo que significaría "midstream".
dandavis

Respuestas:

165

Esa es una de las trampas de JavaScript: inserción automática de punto y coma. Las líneas que no terminan con un punto y coma, pero que podrían ser el final de una declaración, se terminan automáticamente, por lo que su primer ejemplo se ve efectivamente así:

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

Consulte también la guía de estilo JS de Douglas Crockford , que menciona la inserción de punto y coma.

En su segundo ejemplo, devuelve un objeto (construido por las llaves) con la propiedad javascripty su valor de "fantastic", efectivamente, el mismo que este:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
Residuo
fuente
5
Dato curioso: en algunos motores puede comentar los puntos
Christopher Tarquini
1
@ChrisT: ¿Qué? ¿Cuáles? ¿Se explora esto en alguna parte?
Sean McMillan
1
@SeanMcMillan Definitivamente he leído artículos al respecto, pero parece que no puedo encontrar ninguno de ellos en una búsqueda rápida. Recuerdo que poner return /*y luego */{ comentaría efectivamente el punto y coma oculto en versiones anteriores de Chrome. No estoy seguro si eso todavía se aplica
Christopher Tarquini
2
Debido a estas peculiaridades, me hice una promesa hace 10 años: ¡mantente alejado de la web! Recé para que Interwebs desapareciera ... Desafortunadamente, no salió como estaba planeado, y ahora tengo que luchar con estos problemas también. El karma es una
mierda
1
He visto gente que está religiosamente en contra del punto y coma en JavaScript, siempre me he preguntado qué hacen con ese tiempo extra que ahorran al no poner punto y coma.
Iman Mohamadi
9

Javascript no requiere punto y coma al final de las declaraciones, pero el inconveniente es que tiene que adivinar dónde están los puntos y comas. La mayoría de las veces esto no es un problema, pero a veces inventa un punto y coma donde no pretendía.

Un ejemplo de la publicación de mi blog sobre esto ( Javascript, casi no basado en líneas ):

Si formatea el código de esta manera:

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

Entonces se interpreta así:

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

La declaración de retorno toma su forma sin parámetros y el argumento se convierte en una declaración propia.

Lo mismo sucede con tu código. La función se interpreta como:

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

Personalmente, prefiero el estilo Allman por su legibilidad (frente al estilo K&R).

En vez de…

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

Me gusta…

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

  return obj;
}

Pero esta es una solución alternativa. Aunque puedo vivir con eso.

Michael R
fuente
3
Creo que deberíamos evitar las preferencias personales que se desvíen de la corriente principal. Debemos seguir las elecciones de la mayoría, lo que promueve la coherencia, lo que aumentará la legibilidad
Jowen
1
Encuentro su código más legible que el K&R. Bastante subjetivo cuando te refieres a "legible"
Bran
Yo también prefiero el Allman ... pero debido a ASI, cuando necesito devolver un objeto, dejo el semi en la misma línea que el retorno. Prefiero esto que agregar una línea "var x =" ...
Mik
1

Es porque javascript suele poner ";" al final de cada línea, así que, básicamente, cuando tienes return {en la misma línea, el motor javascript ve que habrá algo más, y cuando está en una línea nueva, cree que olvidaste poner ";", y lo pone por ti.

Cichy
fuente
1
No entiendo por qué las respuestas de Cichy, Darin e Ivo fueron rechazadas.
BoltClock
1

Las llaves aquí indican la construcción de un nuevo objeto. Por lo tanto, su código es equivalente a:

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

que funciona mientras que si escribe:

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

ya no funciona.

Darin Dimitrov
fuente
0

De hecho, el problema es la inyección de punto y coma como se describe anteriormente. Acabo de leer una buena publicación de blog sobre este tema. Explica este problema y mucho más sobre javascript. También contiene algunas buenas referencias. Puedes leerlo aqui

Ivo van der Wijk
fuente
Sí, también leí eso, después de leer, pregunto aquí para explicar mejor por la mente maestra de js.
JustLearn