-
Notifications
You must be signed in to change notification settings - Fork 0
/
14-4.html
206 lines (194 loc) · 6.65 KB
/
14-4.html
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="./public/favicon.ico" />
<meta http-equiv="cache-control" content="no-cache" />
<title></title>
<link rel="stylesheet" href=" https://necolas.github.io/normalize.css/8.0.1/normalize.css" />
<link rel="stylesheet" href="./hightlight/default.min.css" />
<link rel="stylesheet" href="./css/main.css" />
<link rel="stylesheet" href="./css/copybutton.css" />
<link rel="stylesheet" href="./css/hightlight.css" />
<script src="./hightlight/hightlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BEVZJDBC7Z"></script>
<script src="./js/gtag.js"></script>
</head>
<body>
<header>
<nav>
<h1>
<span id="toggle-menu"></span>
<a href="index.html"></a>
</h1>
</nav>
</header>
<main>
<aside>
<nav></nav>
</aside>
<article>
<h2 id="14-4">14-4 Operators-Optional chaining (?.)</h2>
<h3>語法</h3>
<ul>
<li>obj?.prop</li>
<li>obj?.[expr]</li>
<li>arr?.[index]</li>
<li>func?.(args)</li>
</ul>
<h3>描述</h3>
<p>
當串連物件裡面的參照或方法可能是 undefined 或 null
時,可選串連運算子提供簡單的方法去存取這些串連物件下的值。舉例來說,當一個物件 obj
是巢狀結構時,在沒有可選串連之下,要去查找一深層的屬性值需要驗證每層間的參照連結:
</p>
<pre><code class="language-js">
function main(config){
// const dbHost = config && config.db && config.db.host;
const dbHost = config?.db?.host;
console.log(dbHost)
}
main()
// undefined
main({
db:{
host: '192.168.0.1',
username: 'root'
},
cache:{
host: '192.168.0.2',
username: 'admin'
},
})
// '192.168.0.1'
</code></pre>
<pre><code class="language-js">
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah',
},
};
const dogName = adventurer.dog?.name;
console.log(dogName);
// Expected output: undefined
console.log(adventurer.someNonExistentMethod?.());
// Expected output: undefined
</code></pre>
<h3>可選串連呼叫函數</h3>
<p>
你可以使用可選串連來嘗試呼叫一個或許沒有存在的方法。這可能有助於,舉例來說,使用一些未能提供服務的
API
,這可能因為過時的應用或是使用者的裝置未能支援某種功能。當需要使用的方法並不存在時,透過可選串連去進行呼叫將不會抛出錯誤,取而代之的是回傳
undefined :
</p>
<pre><code class="language-js">
let result = someInterface.customMethod?.();
</code></pre>
<p>
備註: 假如物件有同樣的屬性名稱,而不是一個方法,使用 ?. 將會抛出 TypeError 錯誤 (x.y
不是一個函數)。
</p>
<h3>處理回呼函式或事件處理器</h3>
<p>
如果你使用回呼函式,或是透過解構賦值來擷取物件中的方法,你可能會因為這些方法沒有存在,而無法進行呼叫,除非你事先驗證其存在性。所以,你可以利用
?. 來避免這樣的測試:
</p>
<pre><code class="language-js">
// 在 ES2019 下撰寫
function doSomething(onContent, onError) {
try {
// ... 對資料進行一些處理
} catch (err) {
if (onError) {
// 測試 onError 是否真的存在
onError(err.message);
}
}
}
</code></pre>
<pre><code class="language-js">
// 使用可選串連進行函式呼叫
function doSomething(onContent, onError) {
try {
// ... 對資料進行一些處理
} catch (err) {
onError?.(err.message); // 就算 onError 是 undefined 也不會抛出錯誤
}
}
</code></pre>
<h3>可選串連表述式</h3>
<p>你也可以在方括號屬性存取表達式中使用可選串連:</p>
<pre><code class="language-js">
let nestedProp = obj?.["prop" + "Name"];
</code></pre>
<h3>矩陣項目的可選串連</h3>
<pre><code class="language-js">
let arrayItem = arr?.[42];
</code></pre>
<p>
這個範例會找出 Map 物件中一個鍵為 bar 成員的 name
屬性值,但事實上並沒有相關成員。所以結果為 undefined 。
</p>
<pre><code class="language-js">
let myMap = new Map();
myMap.set("foo", { name: "baz", desc: "inga" });
let nameBar = myMap.get("bar")?.name;
</code></pre>
<h3>短路式運算</h3>
<p>
當可選串連接上表述式時,如果左邊的運算數值是 null 或 undefined
,表述式則不會被運算。舉例來說:
</p>
<pre><code class="language-js">
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 因為 x 沒有遞增,所以為 0
</code></pre>
<h3>串接多個可選串連</h3>
<p>在巢狀結構中可以使用多次的可選串連:</p>
<pre><code class="language-js">
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls", // 詳細地址 address 並不知道
},
};
let customerCity = customer.details?.address?.city;
// … 同樣地,串接多個可選串連來呼叫函式也是湊效的
let duration = vacations.trip?.getTime?.();
</code></pre>
<h3>使用空值合併運算子</h3>
<p>在可選串連後可以使用空值合併運算子來編配預設值,如果無法在屬性串連中取得值:</p>
<pre><code class="language-js">
let customer = {
name: "Carl",
details: { age: 82 },
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
</code></pre>
<p>資料來源:</p>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining"
>
https://developer.mozilla.org/.../Optional_chaining
</a>
</p>
<p>
<a href="https://www.youtube.com/watch?v=PbjyX5lDC-I">
https://www.youtube.com/watch?v=PbjyX5lDC-I
</a>
</p>
</article>
</main>
</body>
<script type="module" src="./js/main.js"></script>
</html>