Precedencia de operadores
La precedencia de operadores determina el orden en el cual los operadores son evaluados uno respecto del otro. Los operadores con mayor precedencia se convierten en los operandos de los operadores con menor precedencia.
Pruébalo
Precedencia y Asociatividad
Considere la expresión descrita debajo. Note que OP1
y OP2
son ambos ejemplos de operadores.
a OP1 b OP2 c
Si OP1
y OP2
tienen diferente niveles de precedencia (véase la tabla debajo), el operador
con la precedencia más alta va primero y la asociatividad no importa. Observe como la multiplicación
tiene mayor precedencia que la suma y se ejecuta primero, a pesar de que la suma se escribe primero en el código.
console.log(3 + 10 * 2); // muestra 23
console.log(3 + (10 * 2)); // muestra 23 porque los paréntesis son superfluos
console.log((3 + 10) * 2); // muestra 26 porque los paréntesis cambian el orden
La asociatividad a la izquierda (de izquierda a derecha) significa que es procesado como
(a OP1 b) OP2 c
, mientras que la asociatividad a la derecha (de derecha a izquierda) significa que es interpretado como
a OP1 (b OP2 c)
. Los opearadores de asignación son de asociatividad a la derecha, entonces se puede escribir:
a = b = 5; // es igual a escribir a = (b = 5);
con el resultado esperado de que a
y b
obtienen el valor 5. Esto
es porque el operador de asignación retorna el valor que es asignado. Primero,
b
es establecido en 5. Luego a
también es establecida en 5, el valor de retorno
de b = 5
, también conocido como el operando de la derecha de la asignación.
Como otro ejemplo, el operador de exponenciación tiene la particularidad de tener asociatividad a la derecha, a diferencia de los restantes operadores aritméticos que poseen asociatividad a la izquierda. Es interesante notar que, el order de evaluación siempre es de izquierda a derecha sin importar la asociatividad y la precedencia.
Código | Salida |
js
|
Evaluando el lado izquierdo Evaluando el lado derecho 3 |
js
|
Evaluando el lado izquierdo Evaluando el lado derecho 8 |
La diferencia en asociatividad entra en juego cuando hay múltiples operadores con la misma precedencia. Con un único operador u operadores con diferente precedencia, la asociatividad no afecta la salida, como puede verse en el ejemplo de arriba. En el ejemplo debajo, observe como la asociatividad afecta la salida cuando múltiples operadores idénticos son usados.
Código | Saludo |
js
|
Evaluando el lado izquierdo Evaluando el lado medio Evaluando el lado derecho 1 |
js
|
Evaluando el lado izquierdo Evaluando el lado medio Evaluando el lado derecho 512 |
js
|
Evaluando el lado izquierdo Evaluando el lado medio Evaluando el lado derecho 64 |
Viendo los fragmentos de códigos de arriba, 6 / 2 / 3
es lo mismo que
(6 / 2) / 3
porque la división es asociativa a la izquierda. La potencia, por otro lado,
es asociativa a la derecha, entonces 2 ** 3 ** 2
es lo mismo que
2 ** (3 ** 2)
. Por lo tanto, hacer (2 ** 3) ** 2
cambia el orden
y el resultado en el 64 que se ve en la tabla de arriba.
Recuerde que la precedencia viene antes de la asociatividad. Entonces, mezclando
división y potencia, esta última precede a la división. Por ejemplo,
2 ** 3 / 3 ** 2
resulta en 0.8888888888888888 porque es lo mismo que hacer
(2 ** 3) / (3 ** 2)
.
Nota sobre agrupamiento y operadores de cortocircuito
En la tabla debajo, Agrupamiento se lista con la mayor precedencia.
Sin embargo, esto no siempre significa que la expresión dentro de los símbolos
de agrupación ( … )
es evaluada primero, especialmente cuando se trata de
cortocircuitos.
Cortocircuitar es una jerga para la evaluación condicional. Por ejemplo, en la expresión
a && (b + c)
, si a
es falsy, entonces
la expresión (b + c)
no será evaluada, incluso si está dentro de
paréntesis. Se podría decir que el operador de conjunción lógica ("&&") está
"cortocircuitado". Junto con la conjunción lógica, otros operadores cortocircuitados
son la disyunción lógica ("||"), la coalescencia nula ("??"), el encadenamiento opcional ("?."),
y el operador condicional ternario. A continuación, algunos ejemplos.
a || (b * c); // evalúa primero `a`, luego produce `a` si `a` es "truthy"
a && (b < c); // evalúa primero `a`, luego produce `a` si `a` es "falsy"
a ?? (b || c); // evalúa primero `a`, luego produce `a` si `a` no es `null` ni `undefined`
a?.b.c; // evalúa primero `a`, luego produce `undefined` si `a` es `null` ó `undefined`
Ejemplos
3 > 2 && 2 > 1;
// Retorna `true`
3 > 2 > 1;
// Retorna `false` porque 3 > 2 es `true`, luego `true` es convertido a 1
// por coerción de tipos, luego `true` > 1 se convierte en 1 > 1, que es
// `false`. Agregar paréntesis hace que las cosas se vean claras: (3 > 2) > 1.
Tabla
La siguiente tabla lista los operadores en orden de mayor precedencia (19) a menor precedencia (1).
Nótese que la sintaxis spread está intencionalmente excluída de la tabla — porque, citando una respuesta en Stack Overflow, "la sintaxis spread no es un operador y por lo tanto no tiene una precedencia. Es parte de la sintaxis de arreglos literales y llamadas a funciones (y objetos literales)."
Precedencia | Tipo de operador | Asociatividad | Operadores individuales |
---|---|---|---|
19 | Agrupamiento | n/a | ( … ) |
18 | Acceso a propiedades (notación por punto) | a la izquierda | … . … |
Acceso a propiedades (notación por corchetes) | a la izquierda | … [ … ] |
|
new (con lista de argumentos) |
n/a | new … ( … ) |
|
Llamada a función | a la izquierda |
… ( … )
|
|
Encadenamiento opcional | a la izquierda | ?. |
|
17 |
new (sin lista de argumentos)
|
a la derecha | new … |
16 | Incremento sufijo | n/a | … ++ |
Decremento sufijo | … -- |
||
15 | NOT lógico (!) | a la derecha | ! … |
NOT a nivel de bits (~) | ~ … |
||
Suma unaria (+) | + … |
||
Negación unaria (-) | - … |
||
Incremento prefijo | ++ … |
||
Decremento prefijo | -- … |
||
typeof |
typeof … |
||
void |
void … |
||
delete |
delete … |
||
await |
await … |
||
14 | Potenciación (**) | a la derecha | … ** … |
13 | Multiplicación (*) | a la izquierda | … * … |
División (/) | … / … |
||
Resto (%) | … % … |
||
12 | Adición (+) | a la izquierda | … + … |
Sustracción (-) | … - … |
||
11 | Desplazamiento de bits a la izquierda (<<) | a la izquierda | … << … |
Desplazamiento de bits a la derecha (>>) | … >> … |
||
Desplazamiento de bits a la derecha sin signo (>>>) | … >>> … |
||
10 | Menor a (<) | a la izquierda | … < … |
Menor o igual a (<=) | … <= … |
||
Mayor a (>) | … > … |
||
Mayor o igual a (>=) | … >= … |
||
in |
… in … |
||
instanceof |
… instanceof … |
||
9 | Igualdad (==) | a la izquierda | … == … |
Desigualdad (!=) | … != … |
||
Igualdad estricta (===) | … === … |
||
Desigualdad estricta (!==) | … !== … |
||
8 | AND a nivel de bits (&) | a la izquierda | … & … |
7 | XOR a nivel de bits (^) | a la izquierda | … ^ … |
6 | OR a nivel de bits (|) | a la izquierda | … | … |
5 | AND lógico (&&) | a la izquierda | … && … |
4 | OR lógico (||) | a la izquierda | … || … |
Operador de coalescencia nula (??) | a la izquierda | … ?? … |
|
3 | Operador condicional (ternario) | a la derecha | … ? … : … |
2 | Asignación | a la derecha | … = … |
… += … |
|||
… -= … |
|||
… **= … |
|||
… *= … |
|||
… /= … |
|||
… %= … |
|||
… <<= … |
|||
… >>= … |
|||
… >>>= … |
|||
… &= … |
|||
… ^= … |
|||
… |= … |
|||
… &&= … |
|||
… ||= … |
|||
… ??= … |
|||
yield |
a la derecha | yield … |
|
yield* |
yield* … |
||
1 | Operador coma | a la izquierda | … , … |