curiosidades con llaves en javascript

Tengo una duda sobre javascript:

¿Son importantes las llaves {} en javascript?

Sé que es importante para separar las distintas instruccionesy saber que ejecutar en casa caso y también mantener el código más entendible, ya que por ejemplo si un condicional if tiene una sola instrucción no son obligatorias según los manuales. Pero cuando son más de una instrucción son obligatorias según la mayoría de los manuales.

Ahora yo me pregunto ¿es solo para eso?, o pasa algo mas si por ejemplo en un condicional if con varias instrucciones no pongo las llaves. En ejemplos que he probado con un if sin llaves y varias instrucciones no pasa absolutamente nada y ejecuta todas las instrucciones perfectamente.
Hola!

En general, los lenguajes que utilizan este tipo de formato (con delimitadores - C#, Java, PHP, etc.), las llaves no son obligatorias, sino que le dan el sentido lógico a las expresiones. En el fondo, si no las pones, el compilador o intérprete ejecutarán cada instrucción sin parar, pero pueden haber casos donde quieres hacer más de una cosa dependiendo de una condición específica.

Por ejemplo, imagina que te pidan ejecutar las funciones func1 y func2 cuando la condición (algo que sea true) se cumpla:

for(var i = 0; i < arreglo.length; i++) {
    if (condicion) {
        func1();
        func2();
    }

    // Realizas otras operaciones
}

En este caso, si no pusieras las llaves, sólo se ejecutaría la func1 cuando la condicion se cumpla, mientras que la func2 se ejecutaría por cada elemento, siendo que el requisito dice ejecutar ambas funciones cuando la condición se cumpla.

Otro ejemplo, más funcional, sería recorrer un arreglo para modificar su contenido usando while:

var arreglo = [ 10, 20, 30 ];
var i = 0;

while (i < arreglo.length) {
    arreglo[i] = i * 3;
    i++;
}

En este caso, si no usas las llaves estarías creando un infinite loop (si pruebas lo siguiente, tendrás que cerrar el navegador y volver a abrirlo o deshabilitar javascript):

var arreglo = [ 10, 20, 30 ];
var i = 0;

while (i < arreglo.length) // i [B]siempre[/B] será 0 pues la instrucción [B]i++[/B] nunca se alcanza y se crea una condición infinita.
    arreglo[i] = i * 3;

i++;

Es por esto que se necesitan las llaves y delimitadores en general.

Otro beneficio es que ayudan a mejorar la legibilidad del código, pues se nota la intención del programador.

Por último, existe una herramienta llamada jslint, que te ayuda a corregir el código Javascript. Esta herramienta define, por defecto, que todas las condiciones (if...else), for y while, deben usar las llaves para su definición y, en vista de que muchos lo utilizamos, esto se ha convertido en una convención.
Entonces me expliqué mal :P.

¿No dijiste que si no las pones las llaves, el compilador o intérprete ejecutarán cada instrucción sin parar?

Claro, pero me refiero al caso de que hayan estructuras de control (if...else, for, while y do...while). De hecho, el compilador/intérprete ejecutan todas las instrucciones sin parar, sólo que cuando existe un if...else o un control de repetición (for, while, etc.), el compilador/intérprete salta o ejecuta las instrucciones dentro del grupo delimitado por las llaves.

Imagina que eres el intérprete (en el caso de Javascript, es un intérprete) y debes interpretar la siguiente instrucción:

var a = 9;
var b = 15;

if ((a % 2) == 0)
  b += a + b;
// b sigue siendo 15, pues la condición nunca se ejecuta.
b += a * b; 

El intérprete hará lo siguiente:

- Asignar la variable a el valor 9.
- Asignar a la variable b el valor 15.
- Sólo si el resto de dividir a en 2 es igual a 0 -> Agregar a b el valor de a + b.
- Agregar a la variable b el valor de a * b.

En este caso, el valor final de b sería 150. ¿Pero qué pasa si lo que te pidieron era ejecutar ambas operaciones sólo si la condición de que a sea un número para fuera cierta? El programa estaría mal, pues el resultado esperado de b es 15:

var a = 9;
var b = 15;

if ((a % 2) == 0) { // Nunca se ejecuta, pues a no es par.
  b += a + b;
  b += a * b; 
}

He puesto un código parecido al tuyo y cuando llega al condicional if ejecuta las dos instrucciones no la primera solo como comentas. Y en la condición del bucle si se ejecuta siempre solo document.write(i + "<br>")

Claro, ese es el resultado esperado.

En este caso, si no pusieras las llaves, sólo se ejecutaría la func1 cuando la condición se cumpla, mientras que la func2 se ejecutaría por cada elemento, siendo que el requisito dice ejecutar ambas funciones cuando la condición se cumpla.

Lo que digo es que la func1 se ejecuta sólo cuando la condición se cumpla, pero func2 se ejecutará por cada elemento sin importar que la condición se cumpla o no. Ahora, si pusieras unas llaves alrededor de ambas funciones, entonces ambas funciones sólo se ejecutarán al cumplirse la condición.

¿Me expliqué mejor? Jejeje.
Lo que digo es que la func1 se ejecuta sólo cuando la condición se cumpla, pero func2 se ejecutará por cada elemento sin importar que la condición se cumpla o no. Ahora, si pusieras unas llaves alrededor de ambas funciones, entonces ambas funciones sólo se ejecutarán al cumplirse la condición.

Me estaba imaginaba esta respuesta y me imagino que será porque en un condicional if en javascript si tiene una sola instrucción no es obligatorio poner las llaves, solo cuando haya más de una instrucción, pero se recomienda ponerlas siempre como hemos estado comentando. Esto lo he leído siempre sobre javascript:

"...Estas llaves han de colocarse siempre, excepto en el caso de que sólo haya una instrucción como acciones a realizar, que son opcionales"

Me imagino que al no ponerle las llaves al if javascript asume que tiene dentro de ese condicional una sola instrucción y solo ejecuta la primera instrucción del ejemplo y la otra como bien dices la func2 se ejecutará por cada elemento sin importar que la condición se cumpla o no, esta en este caso es como si estuviera fuera del if y por eso se ejecuta siempre. ¿Estoy en lo cierto?

de resto todo ok jejeje
Exacto! Eso es lo que quise decir :).

Como has dicho:

Si no hay llaves, entonces se asume que sólo hay 1 instrucción y el resto queda fuera.

Esto es con todas las expresiones de control (excepto switch que, hasta donde sé, necesita las llaves). Por si acaso, todo lo que hemos hablado ahora aplica también a otros lenguajes como Java, PHP, C#, C/C++, etc.