aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html')
-rw-r--r--files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html203
1 files changed, 203 insertions, 0 deletions
diff --git a/files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html b/files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html
new file mode 100644
index 0000000000..6b45bc4aad
--- /dev/null
+++ b/files/zh-cn/web/javascript/reference/operators/optional_chaining/index.html
@@ -0,0 +1,203 @@
+---
+title: 可选链操作符
+slug: Web/JavaScript/Reference/Operators/Optional_chaining
+tags:
+ - '?.'
+ - JavaScript
+ - Optional chaining (?.)
+ - Reference
+ - 参考
+ - 可选链
+ - 语言特性
+ - 运算符
+ - 链式调用
+translation_of: Web/JavaScript/Reference/Operators/Optional_chaining
+original_slug: Web/JavaScript/Reference/Operators/可选链
+---
+<div>{{JSSidebar("Operators")}}</div>
+
+<p><strong>可选链</strong>操作符( <strong><code>?.</code></strong> )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。<code>?.</code> 操作符的功能类似于 <code>.</code> 链式操作符,不同之处在于,在引用为空(<a href="https://wiki.developer.mozilla.org/en-US/docs/Glossary/nullish">nullish</a> ) ({{JSxRef("null")}} 或者 {{JSxRef("undefined")}}) 的情况下不会引起错误,该表达式短路返回值是 <code>undefined</code>。与函数调用一起使用时,如果给定的函数不存在,则返回 <code>undefined</code>。</p>
+
+<p>当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。</p>
+
+<div>{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", "taller")}}</div>
+
+
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox notranslate"><var>obj</var>?.<var>prop</var>
+<var>obj</var>?.[<var>expr</var>]
+<var>arr</var>?.[<var>index</var>]
+<var>func</var>?.(<var>args</var>)
+</pre>
+
+<h2 id="描述">描述</h2>
+
+<p>通过连接的对象的引用或函数可能是 <code>undefined</code> 或 <code>null</code> 时,可选链操作符提供了一种方法来简化被连接对象的值访问。</p>
+
+<p>比如,思考一个存在嵌套结构的对象 <code>obj</code>。不使用可选链的话,查找一个深度嵌套的子属性时,需要验证之间的引用,例如:</p>
+
+<pre class="brush: js notranslate">let nestedProp = obj.first &amp;&amp; obj.first.second;</pre>
+
+<p>为了避免报错,在访问<code>obj.first.second</code>之前,要保证 <code>obj.first</code> 的值既不是 <code>null</code>,也不是 <code>undefined</code>。如果只是直接访问 <code>obj.first.second</code>,而不对 <code>obj.first</code> 进行校验,则有可能抛出错误。</p>
+
+<p>有了可选链操作符(<code>?.</code>),在访问 <code>obj.first.second</code> 之前,不再需要明确地校验 <code>obj.first</code> 的状态,再并用短路计算获取最终结果:</p>
+
+<pre class="brush: js notranslate">let nestedProp = obj.first?.second;</pre>
+
+<p>通过使用 <code>?.</code> 操作符取代 <code>.</code> 操作符,JavaScript 会在尝试访问 <code>obj.first.second</code> 之前,先隐式地检查并确定 <code>obj.first</code> 既不是 <code>null</code> 也不是 <code>undefined</code>。如果<code>obj.first </code>是 <code>null</code> 或者 <code>undefined</code>,表达式将会短路计算直接返回 <code>undefined</code>。</p>
+
+<p>这等价于以下表达式,但实际上没有创建临时变量:</p>
+
+<pre class="brush: js notranslate">let temp = obj.first;
+let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);</pre>
+
+<h3 id="可选链与函数调用">可选链与函数调用</h3>
+
+<p>当尝试调用一个可能不存在的方法时也可以使用可选链。这将是很有帮助的,比如,当使用一个API的方法可能不可用时,要么因为实现的版本问题要么因为当前用户的设备不支持该功能。</p>
+
+<p>函数调用时如果被调用的方法不存在,使用可选链可以使表达式自动返回<code>undefined</code>而不是抛出一个异常。</p>
+
+<pre class="brush: js notranslate">let result = someInterface.customMethod?.();</pre>
+
+<div class="blockIndicator note">
+<p><strong>注意:</strong> 如果存在一个属性名且不是函数, 使用 <code>?.</code> 仍然会产生一个 {{JSxRef("TypeError")}} 异常 (<code>x.y</code><code> is not a function</code>).</p>
+</div>
+
+<div class="blockIndicator note">
+<p><strong>注意:</strong> 如果 <code>someInterface</code> 自身是 <code>null</code> 或者 <code>undefined</code> ,异常 {{JSxRef("TypeError")}} 仍会被抛出 <code>someInterface is null</code> 如果你希望允许 <code>someInterface</code> 也为 <code>null</code> 或者 <code>undefined</code> ,那么你需要像这样写 <code>someInterface?.customMethod?.()</code></p>
+</div>
+
+<h4 id="处理可选的回调函数或者事件处理器">处理可选的回调函数或者事件处理器</h4>
+
+<p>如果使用<a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">解构赋值</a>来解构的一个对象的回调函数或 fetch 方法,你可能得到不能当做函数直接调用的不存在的值,除非你已经校验了他们的存在性。使用<code>?.</code>的你可以忽略这些额外的校验:</p>
+
+<pre class="brush: js notranslate">// ES2019的写法
+function doSomething(onContent, onError) {
+ try {
+ // ... do something with the data
+ }
+ catch (err) {
+ if (onError) { // 校验onError是否真的存在
+ onError(err.message);
+ }
+ }
+}
+</pre>
+
+<pre class="brush: js notranslate">// 使用可选链进行函数调用
+function doSomething(onContent, onError) {
+ try {
+ // ... do something with the data
+ }
+ catch (err) {
+ onError?.(err.message); // 如果onError是undefined也不会有异常
+ }
+}
+</pre>
+
+<h3 id="可选链和表达式">可选链和表达式</h3>
+
+<p>当使用<a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors#方括号表示法">方括号与属性名</a>的形式来访问属性时,你也可以使用可选链操作符:</p>
+
+<pre class="brush: js notranslate">let nestedProp = obj?.['prop' + 'Name'];</pre>
+
+<h3 id="可选链不能用于赋值">可选链不能用于赋值</h3>
+
+<pre class="notranslate"><code>let object = {};
+object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment</code></pre>
+
+<h3 id="可选链访问数组元素">可选链访问数组元素</h3>
+
+<pre class="notranslate">let arrayItem = arr?.[42];</pre>
+
+<h2 id="例子">例子</h2>
+
+<h3 id="基本例子">基本例子</h3>
+
+<p>如下的例子在一个不含 <code>bar</code> 成员的 Map 中查找 <code>bar</code> 成员的 <code>name</code> 属性,因此结果是 <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="短路计算">短路计算</h3>
+
+<p>当在表达式中使用可选链时,如果左操作数是 <code>null</code> 或 <code>undefined</code>,表达式将不会被计算,例如:</p>
+
+<pre class="brush: js notranslate">let potentiallyNullObj = null;
+let x = 0;
+let prop = potentiallyNullObj?.[x++];
+
+console.log(x); // x 将不会被递增,依旧输出 0
+</pre>
+
+<h3 id="连用可选链操作符">连用可选链操作符</h3>
+
+<p>可以连续使用可选链读取多层嵌套结构:</p>
+
+<pre class="brush: js notranslate">let customer = {
+ name: "Carl",
+ details: {
+ age: 82,
+ location: "Paradise Falls" // details 的 address 属性未有定义
+ }
+};
+let customerCity = customer.details?.address?.city;
+
+// … 可选链也可以和函数调用一起使用
+let duration = vacations.trip?.getTime?.();
+</pre>
+
+<h3 id="使用空值合并操作符">使用空值合并操作符</h3>
+
+<p>{{JSxRef("Operators/Nullish_Coalescing_Operator", "空值合并操作符")}}可以在使用可选链时设置一个默认值:</p>
+
+<pre class="brush: js notranslate"><code>let customer = {
+ name: "Carl",
+ details: { age: 82 }
+};
+let customerCity = customer?.city ?? "暗之城";
+console.log(customerCity); // “暗之城”</code></pre>
+
+<h2 id="规范">规范</h2>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">规范</th>
+ <th scope="col">状态</th>
+ <th scope="col">备注</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{SpecName('ESDraft', '#prod-OptionalExpression', 'optional expression')}}</td>
+ <td>Stage 4</td>
+ <td></td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<div>
+
+
+<p>{{Compat("javascript.operators.optional_chaining")}}</p>
+
+<h3 id="Implementation_Progress">Implementation Progress</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 the latest release of each browser's JavaScript engine.</p>
+
+<p>{{EmbedTest262ReportResultsTable("optional-chaining")}}</p>
+</div>
+
+<h2 id="参见">参见</h2>
+
+<ul>
+ <li>{{JSxRef("Operators/Nullish_Coalescing_Operator", "空值合并操作符")}}</li>
+ <li><a href="https://github.com/tc39/proposals">TC39 提案</a></li>
+</ul>