1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
---
title: Encadenamiento opcional
slug: Web/JavaScript/Referencia/Operadores/Encadenamiento_opcional
translation_of: Web/JavaScript/Reference/Operators/Optional_chaining
---
<div>{{JSSidebar("Operators")}}</div>
<p>El operador de <strong>encadenamiento opcional</strong> <strong><code>?.</code></strong> permite leer el valor de una propiedad ubicada dentro de una cadena de objetos conectados sin tener que validar expresamente que cada referencia en la cadena sea válida. <span class="seoSummary">El operador <code>?.</code> funciona de manera similar a el operador de encadenamiento <code>.</code>, excepto que en lugar de causar un error si una referencia es <a href="/en-US/docs/Glossary/nullish">casi-nula</a> ({{JSxRef("null")}} o {{JSxRef("undefined")}}), la expresión hace una evaluación de circuito corto con un valor de retorno de <code>undefined</code>.</span> Cuando se usa con llamadas a funciones, devuelve <code>undefined</code> si la función dada no existe.</p>
<p>Esto da como resultado expresiones más cortas y simples cuando se accede a propiedades encadenadas dónde existe la posibilidad de que falte una referencia. También puede ser útil al explorar el contenido de un objeto cuando no hay una garantía conocida de qué propiedades se requieren.</p>
<div>{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", "taller")}}</div>
<div class="hidden">The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</div>
<h2 id="Sintaxis">Sintaxis</h2>
<pre class="syntaxbox"><var>obj</var>?.<var>prop</var>
<var>obj</var>?.[<var>expr</var>]
<em>arr</em>?.[<var>index</var>]
<var>func</var>?.(<var>args</var>)
</pre>
<h2 id="Descripción">Descripción</h2>
<p>El operador de encadenamiento opcional proporciona una forma de simplificar el acceso a los valores a través de objetos conectados cuando es posible que una referencia o función sea <code>undefined</code> o <code>null</code>.</p>
<p>Por ejemplo, considere un objeto <code>obj</code> que tiene una estructura anidada. Sin encadenamiento opcional, buscar una subpropiedad profundamente anidada requiere validar las referencias intermedias, como:</p>
<pre class="brush: js">let nestedProp = obj.first && obj.first.second;
</pre>
<p>Se confirma que el valor de <code>obj.first</code> no es <code>null</code> (y no es <code>undefined</code>) antes de acceder al valor de <code>obj.first.second</code>. Esto evita el error que ocurriría si simplemente accediera a <code>obj.first.second</code> directamente sin probar <code>obj.first</code>.</p>
<p>Sin embargo, con el operador de encadenamiento opcional (<code>?.</code>), No tiene que probar explícitamente, ni realizar una evaluación de circuito corto basada en el estado de <code>obj.first</code> antes de intentar acceder a <code>obj.first.second</code>:</p>
<pre class="brush: js">let nestedProp = obj.first?.second;
</pre>
<p>Al usar el operador <code>?.</code> en lugar de solo el <code>.</code>, JavaScript sabe verificar implícitamente para asegurarse de que <code>obj.first</code> no es <code>null</code> o <code>undefined</code> antes de intentar acceder <code>obj.first.second</code>. Si <code>obj.first</code> es <code>null</code> o <code>undefined</code>, la expresión hace una evaluación de circuito corto automáticamente y retorna <code>undefined</code>.</p>
<p>Esto es equivalente a lo siguiente, excepto que la variable temporal es de hecho no creada:</p>
<pre class="brush: js">let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
</pre>
<h3 id="Encadenamiento_opcional_con_llamadas_a_funciones">Encadenamiento opcional con llamadas a funciones</h3>
<p>Puede usar el encadenamiento opcional cuando intente llamar a un método que puede no existir. Esto puede ser útil, por ejemplo, cuando se usa una API en la que un método podría no estar disponible, ya sea debido a la antigüedad de la implementación o debido a una característica que no está disponible en el dispositivo del usuario.</p>
<p>El uso de encadenamiento opcional con llamadas a funciones hace que la expresión regrese automáticamente <code>undefined</code> en lugar de lanzar una excepción si no se encuentra el método:</p>
<pre class="brush: js">let result = someInterface.customMethod?.();</pre>
<div class="blockIndicator note">
<p><strong>Nota:</strong> Si hay una propiedad con ese nombre y que no es una función, usar <code>?.</code> aún levantará una excepción {{JSxRef("TypeError")}} (<code>x.y</code><code> is not a function</code>).</p>
</div>
<h4 id="Manejo_de_callbacks_opcionales_o_manejadores_de_eventos">Manejo de callbacks opcionales o manejadores de eventos</h4>
<p>Si utiliza callbacks o métodos de recuperación de un objeto con<a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring"> una asignación de desestructuración</a>, es posible que tenga valores inexistentes que no puede llamar como funciones a menos que haya probado su existencia. Usando <code>?.</code>, Puede evitar esta prueba adicional:</p>
<pre class="brush: js">// Escrito a partir de ES2019
function doSomething(onContent, onError) {
try {
// ... hacer algo con los datos
}
catch (err) {
if (onError) { // Probando si onError realmente existe
onError(err.message);
}
}
}
</pre>
<pre class="brush: js">// Usando encadenamiento opcional con llamado de funciones
function doSomething(onContent, onError) {
try {
// ... hacer algo con los datos
}
catch (err) {
onError?.(err.message); // Sin excepción si onError esta undefined
}
}
</pre>
<h3 id="Encadenamiento_opcional_con_expresiones">Encadenamiento opcional con expresiones</h3>
<p>También puede usar el operador de encadenamiento opcional al acceder a propiedades con una expresión usando <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation">la notación de corchetes</a>:</p>
<pre class="brush: js">let nestedProp = obj?.['prop' + 'Name'];
</pre>
<h3 id="El_encadenamiento_opcional_no_es_válido_al_lado_izquierdo_de_una_asignación">El encadenamiento opcional no es válido al lado izquierdo de una asignación</h3>
<pre class="brush: js"><code>let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment</code></pre>
<h3 id="Acceso_a_elementos_de_un_arreglo_con_encadenamiento_opcional">Acceso a elementos de un arreglo con encadenamiento opcional</h3>
<pre class="brush: js">let arrayItem = arr?.[42];</pre>
<h2 id="Ejemplos">Ejemplos</h2>
<h3 id="Ejemplo_básico">Ejemplo básico</h3>
<p>Este ejemplo busca el valor de la propiedad <code>name</code> para el miembro <code>bar</code> en un mapa cuando no existe dicho miembro. El resultado es por lo tanto es <code>undefined</code>.</p>
<pre class="brush: js">let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});
let nameBar = myMap.get("bar")?.name;</pre>
<h3 id="Evaluación_de_circuito_corto">Evaluación de circuito corto</h3>
<p>Cuando se usa el encadenamiento opcional con expresiones, si el operando izquierdo es <code>null</code> o <code>undefined</code>, la expresión no se evaluará. Por ejemplo:</p>
<pre class="brush: js">let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 0 como x no se incrementó
</pre>
<h3 id="Apilando_el_operador_de_encadenamiento_opcional">Apilando el operador de encadenamiento opcional</h3>
<p>Con estructuras anidadas, es posible usar encadenamiento opcional varias veces:</p>
<pre class="brush: js">let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // "detailed address" es desconocida
}
};
let customerCity = customer.details?.address?.city;
// … esto también funciona con la función opcional de encadenamiento
let duration = vacations.trip?.getTime?.();
</pre>
<h3 id="Combinando_con_el_operador_de_fusión_nulo">Combinando con el operador de fusión nulo</h3>
<p>El {{JSxRef("Operators/Nullish_Coalescing_Operator", "operador de fusión nulo", '', 1)}} se puede usar después del encadenamiento opcional para generar un valor predeterminado cuando no se encontró ninguno:</p>
<pre class="brush: js">let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city</pre>
<h2 id="Especificaciones">Especificaciones</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Specification</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#prod-OptionalExpression', 'optional expression')}}</td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidad_de_navegadores">Compatibilidad de navegadores</h2>
<div>
<p>{{Compat("javascript.operators.optional_chaining")}}</p>
</div>
<h3 id="Progreso_de_implementación">Progreso de implementación</h3>
<p>La siguiente tabla proporciona un estado de implementación diaria para esta característica, porque esta característica aún no ha alcanzado la estabilidad entre navegadores. Los datos se generan ejecutando las pruebas de características relevantes en <a href="https://github.com/tc39/test262">Test262</a>, el conjunto de pruebas estándar de JavaScript, en la compilación nocturna o la última versión del motor de JavaScript de cada navegador.</p>
<div>{{EmbedTest262ReportResultsTable("optional-chaining")}}</div>
<h2 id="Ver_también">Ver también</h2>
<ul>
<li>El {{JSxRef("Operators/Nullish_Coalescing_Operator", "Nullish Coalescing Operator", '', 1)}}</li>
</ul>
|