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
188
189
190
191
192
|
---
title: Encadeamento opcional
slug: Web/JavaScript/Reference/Operators/Optional_chaining
translation_of: Web/JavaScript/Reference/Operators/Optional_chaining
---
<div>{{JSSidebar("Operators")}}</div>
<p>O operador de <strong>encadeamento opcional</strong> <strong><code>?.</code></strong> permite a leitura do valor de uma propriedade localizada internamente em uma cadeia de objetos conectados, sem que a validação de cada referência da cadeia seja expressivamente realizada.</p>
<p>O operador <strong><code>?.</code></strong> funciona de maneira similar ao operador <span class="seoSummary"><code>.</code> de encadeament, exceto que, ao invés de causar um erro se a referência é <a href="/en-US/docs/Glossary/nullish">nullish</a> ({{JSxRef("null")}} ou {{JSxRef("undefined")}}), a expressão sofre um "curto-circuito" e retorna com um valor de <code>undefined</code>.</span> Quando utilizado com uma chamada de função, retorna <code>undefined</code> se a função executada não existir.</p>
<p>Isso resulta em expressões mais curtas e simples ao acessar propriedades encadeadas quando a possibilidade de uma referência ser inexistente. Isso também pode auxiliar ao explorar o conteúdo de um objeto quando não existe garantia da existência de determinadas propriedades obrigatórias.</p>
<div>{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", "taller")}}</div>
<div class="hidden">A fonte desse exemplo interativo está armazenada em um repositório no GitHub. Se você gostaria de contribuir para esses exemplos interativos, por favor, clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> e nos envie um pull request.</div>
<h2 id="Sintaxe">Sintaxe</h2>
<pre class="syntaxbox notranslate"><var>obj.val</var>?.<var>prop</var>
<var>obj.val</var>?.[<var>expr</var>]
<em>obj.arr</em>?.[<var>index</var>]
<var>obj.func</var>?.(<var>args</var>)
</pre>
<h2 id="Descrição">Descrição</h2>
<p>O operador de encadeamento opcional provê uma forma de simplificar o acesso a valores através de objetos conectados, quando é possível que uma referência ou função possa ser <code>undefined</code> ou <code>null</code>.</p>
<p>Por exemplo, considere um objeto <code>obj</code> que possui uma estrutura aninhada. Sem o encadeamento opcional, verificar proriedades profundamente aninhadas requer uma validação de referências intermediárias, algo como:</p>
<pre class="brush: js notranslate">let nestedProp = obj.first && obj.first.second;</pre>
<p>O valor de <code>obj.first</code> é confirmadamente não-<code>null</code> (e não-<code>undefined</code>) antes de acessar o valor de <code>obj.first.second</code>. Isso previne o erro que ocorreria se você simplesmente acessasse <code>obj.first.second</code> diretamente sem testar <code>obj.first</code>.</p>
<p>Com o operador de encadeamento opcional (<code>?.</code>), entretanto, você não precisa explicitamente testar e aplicar curto-circuito baseado no estado de <code>obj.first</code> antes de tentar acessar <code>obj.first.second</code>:</p>
<pre class="brush: js notranslate">let nestedProp = obj.first?.second;</pre>
<p>Ao utilizar o operador <code>?.</code> ao invés de apenas <code>.</code>, o JavaScript sabe que deve implicitamente checar e ter certeza que <code>obj.first</code> não é <code>null</code> ou <code>undefined</code> antes de tentar acessar <code>obj.first.second</code>. Se <code>obj.first</code> é <code>null</code> ou <code>undefined</code>, a expressão automaticamente sofrerá curto-circuito, retornando <code>undefined</code>.</p>
<p>Isso é equivalente ao seguinte, exceto que a variável temporária, de fato, não é criada:</p>
<pre class="brush: js notranslate">let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
</pre>
<h3 id="Encadeamento_opcional_com_chamadas_de_funções">Encadeamento opcional com chamadas de funções</h3>
<p>Você pode usar o encadeamento opcional ao tentar chamar um método que pode não existir. Isso pode auxiliar, por exemplo, ao utilizar uma API em que o método está indisponível, seja pela época da implementação ou por causa de uma funcionalidade que ainda não está disponível no dispositivo do usuário.</p>
<p>Usar encadeamento opcional com chamadas de função faz com que a expressão automaticamente retorne <code>undefined</code> ai invés de lançar uma exceção se o método não é encontrado:</p>
<pre class="brush: js notranslate">let result = someInterface.customMethod?.();</pre>
<div class="blockIndicator note">
<p><strong>Note:</strong> Se existe uma propriedade com tal nome e que não é uma função, usando <code>?.</code> ainda lançará a exceção {{JSxRef("TypeError")}} (<code>x.y</code><code> is not a function</code>).</p>
</div>
<h4 id="Lidando_com_callbacks_opcionais_ou_manipuladores_de_eventos">Lidando com callbacks opcionais ou manipuladores de eventos</h4>
<p>Se você usa callbacks ou consulta métodos de objetos com <a href="/pt-BR/docs/Web/JavaScript/Reference/Operators/Atribuicao_via_desestruturacao#Object_destructuring">atribuição via desestruturação</a>, você pode ter valores não-existentes que você não conseguirá chamar como funções, a menos que você tenha testado sua existência. Usando <code>?.</code>, você pode evitar esse teste extra:</p>
<pre class="brush: js notranslate">// Escrito como ES2019
function doSomething(onContent, onError) {
try {
// ... faz algo com os dados
}
catch (err) {
if (onError) { // teste se onError realmente existe
onError(err.message);
}
}
}
</pre>
<pre class="brush: js notranslate">// Usando encadeamento opcional com chamadas de função
function doSomething(onContent, onError) {
try {
// ... faz algo com os dados
}
catch (err) {
onError?.(err.message); // Nenhuma exceção se onError for undefined
}
}
</pre>
<h3 id="Encadeamento_opcional_com_expressões">Encadeamento opcional com expressões</h3>
<p>Você também pode usar o operador de encadeamento opcional ao acessar propriedades com uma expressão usando <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation">assessores de propriedade</a>:</p>
<pre class="brush: js notranslate">let nestedProp = obj?.['prop' + 'Name'];
</pre>
<h3 id="Encadeamento_opcional_não_valid_no_lado_esquerdo_de_uma_atribuição">Encadeamento opcional não valid no lado esquerdo de uma atribuição</h3>
<pre class="brush: js notranslate"><code>let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment</code></pre>
<h3 id="Acesso_a_item_de_Array_com_encadeamento_opcional">Acesso a item de Array com encadeamento opcional</h3>
<pre class="brush: js notranslate">let arrayItem = arr?.[42];</pre>
<h2 id="Exemplos">Exemplos</h2>
<h3 id="Exemplo_básico">Exemplo básico</h3>
<p>Esse exemplo busca plo valor da propriedade <code>name</code> para o membro <code>bar</code> em um map quando não existe tal membro. Portanto, o resultado é <code>undefined</code>.</p>
<pre class="brush: js notranslate">let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});
let nameBar = myMap.get("bar")?.name;</pre>
<h3 id="Avaliação_com_curto-circuito">Avaliação com curto-circuito</h3>
<p>Ao usar o encadeamento opcional com expressões, se o operador do lado esquerdo é <code>null</code> ou <code>undefined</code>, a expressão não será avaliada. Por exemplo:</p>
<pre class="brush: js notranslate">let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 0 já que x não foi incrementado
</pre>
<h3 id="Empilhando_o_operator_de_encadeamento_opcional">Empilhando o operator de encadeamento opcional</h3>
<p>Com estruturadas aninhadas, é possível usar encadeamento opcional múltiplas vezes:</p>
<pre class="brush: js notranslate">let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // endereço detalhado é desconhecido
}
};
let customerCity = customer.details?.address?.city;
// … isso também funcional com encadeamento opcional em chamada de função
let duration = vacations.trip?.getTime?.();
</pre>
<h3 id="Combinando_com_o_operador_de_coalescência_nula_nullish_coalescing">Combinando com o operador de coalescência nula (nullish coalescing)</h3>
<p>O {{JSxRef("Operators/Nullish_Coalescing_Operator", "operador de coalescência nula", '', 1)}} pode ser usado após o encadeamento opcional, para construir um valor padrão quando nada é encontrado:</p>
<pre class="brush: js notranslate">let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Cidade desconhecida";
console.log(customerCity); // Cidade desconhecida</pre>
<h2 id="Especificações">Especificações</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://tc39.es/proposal-optional-chaining/#sec-scope">Proposal for the "optional chaining" operator</a></td>
<td>Stage 4</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidade_de_Navegadores">Compatibilidade de Navegadores</h2>
<div>
<p>{{Compat("javascript.operators.optional_chaining")}}</p>
</div>
<h3 id="Progresso_de_implementação">Progresso de implementação</h3>
<p>The following table provides a daily implementation status for this feature, because this feature has not yet reached cross-browser stability. The data is generated by running the relevant feature tests in <a href="https://github.com/tc39/test262">Test262</a>, the standard test suite of JavaScript, in the nightly build, or latest release of each browser's JavaScript engine.</p>
<div>{{EmbedTest262ReportResultsTable("optional-chaining")}}</div>
<h2 id="Veja_também">Veja também</h2>
<ul>
<li>O {{JSxRef("Operators/Nullish_Coalescing_Operator", "Nullish Coalescing Operator", '', 1)}}</li>
<li><a href="https://github.com/tc39/proposals">TC39 proposals</a></li>
</ul>
|