ìµì
ë ì²´ì´ë(optional chaining) ?.ì ì¬ì©íë©´ íë¡í¼í°ê° ìë ì¤ì²© ê°ì²´ë¥¼ ìë¬ ìì´ ìì íê² ì ê·¼í ì ììµëë¤.
ìµì ë ì²´ì´ëì´ íìí ì´ì
ì´ì ë§ ìë°ì¤í¬ë¦½í¸ë¥¼ ë°°ì°ê¸° ììíë¤ë©´ ìµì ë ì²´ì´ëì´ ë±ì¥íê² ë ë°°ê²½ ìí©ì ì§ì 겪ì´ë³´ì§ ììì ê²ëë¤. ëª ê°ì§ ì¬ë¡ë¥¼ ì¬ííë©´ì ì ìµì ë ì²´ì´ëì´ ë±ì¥íëì§ ììë´ ìë¤.
ì¬ì©ìê° ì¬ë¬ ëª
ìëë° ê·¸ì¤ ëª ëª
ì 주ì ì 보를 ê°ì§ê³ ìì§ ìë¤ê³ ê°ì í´ë´
ìë¤. ì´ë´ ë user.address.street를 ì¬ì©í´ 주ì ì ë³´ì ì ê·¼íë©´ ìë¬ê° ë°ìí ì ììµëë¤.
let user = {}; // 주ì ì ë³´ê° ìë ì¬ì©ì
alert(user.address.street); // TypeError: Cannot read property 'street' of undefined
ë ë¤ë¥¸ ì¬ë¡ë¡ ë¸ë¼ì°ì ìì ëìíë ì½ë를 ê°ë°í ë ë°ìí ì ìë 문ì ê° ììµëë¤. ìë°ì¤í¬ë¦½í¸ë¥¼ ì¬ì©í´ íì´ì§ì ì¡´ì¬íì§ ìë ììì ì ê·¼í´ ììì ì 보를 ê°ì ¸ì¤ë ¤ íë©´ 문ì ê° ë°ìíì£ .
// querySelector(...) í¸ì¶ ê²°ê³¼ê° nullì¸ ê²½ì° ìë¬ ë°ì
let html = document.querySelector('.my-element').innerHTML;
ëª
ì¸ìì ?.ì´ ì¶ê°ë기 ì ì ì´ë° 문ì ë¤ì í´ê²°í기 ìí´ && ì°ì°ì를 ì¬ì©í곤 íìµëë¤.
ìì:
let user = {}; // 주ì ì ë³´ê° ìë ì¬ì©ì
alert( user && user.address && user.address.street ); // undefined, ìë¬ê° ë°ìíì§ ììµëë¤.
ì¤ì²© ê°ì²´ì í¹ì íë¡í¼í°ì ì ê·¼í기 ìí´ ê±°ì³ì¼ í 구ì±ììë¤ì ANDë¡ ì°ê²°í´ ì¤ì í´ë¹ ê°ì²´ë íë¡í¼í°ê° ìëì§ íì¸íë ë°©ë²ì ì¬ì©íìì£ . ê·¸ë°ë° ì´ë ê² AND를 ì°ê²°í´ì ì¬ì©íë©´ ì½ëê° ì주 길ì´ì§ë¤ë ë¨ì ì´ ììµëë¤.
ìµì ë ì²´ì´ëì ë±ì¥
?.ì ?.'ìâì íê° ëìì´ undefinedë nullì´ë©´ íê°ë¥¼ ë©ì¶ê³ undefined를 ë°íí©ëë¤.
ì¤ëª
ì´ ì¥í©í´ì§ì§ ìëë¡ ì§ê¸ë¶í´ íê°í ê²°ê³¼ê° nullì´ë undefinedê° ìë ê²½ì°ì ê°ì´ âìë¤â í¹ì 'ì¡´ì¬íë¤âë¼ê³ íííê² ìµëë¤.
ì´ì ìµì
ë ì²´ì´ëì ì¬ì©í´ user.address.streetì ìì íê² ì ê·¼í´ë´
ìë¤.
let user = {}; // 주ì ì ë³´ê° ìë ì¬ì©ì
alert( user?.address?.street ); // undefined, ìë¬ê° ë°ìíì§ ììµëë¤.
user?.addressë¡ ì£¼ì를 ì½ì¼ë©´ ìëì ê°ì´ user ê°ì²´ê° ì¡´ì¬íì§ ìëë¼ë ìë¬ê° ë°ìíì§ ììµëë¤.
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
ì ìì를 íµí´ ì°ë¦¬ë ?.ì ?. âìâ íê° ëììë§ ëìëê³ , íì¥ì ëì§ ìëë¤ë ì¬ì¤ì ì ì ììµëë¤.
ì°¸ê³ ë¡ ì ìììì ì¬ì©ë user?.ë userê° nullì´ë undefinedì¸ ê²½ì°ë§ ì²ë¦¬í ì ììµëë¤.
userê° nullì´ë undefinedê° ìëê³ ì¤ì ê°ì´ ì¡´ì¬íë ê²½ì°ì ë°ëì user.address íë¡í¼í°ë ìì´ì¼ í©ëë¤. ê·¸ë ì§ ìì¼ë©´ user?.address.streetì ë ë²ì§¸ ì ì°ì°ììì ìë¬ê° ë°ìí©ëë¤.
?.ë ì¡´ì¬íì§ ììë ê´ì°®ì ëììë§ ì¬ì©í´ì¼ í©ëë¤.
ì¬ì©ì 주ì를 ë¤ë£¨ë ì ìììì ë
¼ë¦¬ì userë ë°ëì ìì´ì¼ íëë° addressë íìê°ì´ ìëëë¤. ê·¸ë¬ë user.address?.street를 ì¬ì©íë ê²ì´ ë°ëì§í©ëë¤.
ì¤ìë¡ ì¸í´ userì ê°ì í ë¹íì§ ììë¤ë©´ ë°ë¡ ììë¼ ì ìëë¡ í´ì¼ í©ëë¤. ê·¸ë ì§ ìì¼ë©´ ìë¬ë¥¼ 조기ì ë°ê²¬íì§ ëª»íê³ ëë²ê¹
ì´ ì´ë ¤ìì§ëë¤.
?.ìì ë³ìë ê¼ ì ì¸ëì´ ìì´ì¼ í©ëë¤.ë³ì userê° ì ì¸ëì´ìì§ ìì¼ë©´ user?.anything íê°ì ìë¬ê° ë°ìí©ëë¤.
// ReferenceError: user is not defined
user?.address;
user?.anythingì ì¬ì©íë ¤ë©´ letì´ë const, var를 ì¬ì©í´ user를 ì ìí´ì¼ íì£ . ì´ë ê² ìµì
ë ì²´ì´ëì ì ì¸ì´ ìë£ë ë³ì를 ëìì¼ë¡ë§ ëìí©ëë¤.
ë¨ë½ íê°
?.ë ì¼ìª½ íê°ëìì ê°ì´ ìì¼ë©´ ì¦ì íê°ë¥¼ ë©ì¶¥ëë¤. ì°¸ê³ ë¡ ì´ë° íê° ë°©ë²ì ë¨ë½ íê°(short-circuit)ë¼ê³ ë¶ë¦
ëë¤.
ê·¸ë 기 ë문ì í¨ì í¸ì¶ì ë¹ë¡¯í ?. ì¤ë¥¸ìª½ì ìë ë¶ê° ëìì ?.ì íê°ê° ë©ì·ì ë ëë ì¼ì´ëì§ ììµëë¤.
let user = null;
let x = 0;
user?.sayHi(x++); // ì무 ì¼ë ì¼ì´ëì§ ììµëë¤.
alert(x); // 0, xë ì¦ê°íì§ ììµëë¤.
?.()ì ?.[]
?.ì ì°ì°ìê° ìëëë¤. ?.ì í¨ìë ëê´í¸ì í¨ê» ëìíë í¹ë³í ë¬¸ë² êµ¬ì¡°ì²´(syntax construct)ì
ëë¤.
í¨ì ê´ë ¨ ììì í¨ê» ì¡´ì¬ ì¬ë¶ê° íì¤ì¹ ìì í¨ì를 í¸ì¶í ë ?.()를 ì´ë»ê² ì¸ ì ìëì§ ììë´
ìë¤.
í ê°ì²´ì ë©ìë adminì´ ìì§ë§ ë¤ë¥¸ ê°ì²´ì ìë ìí©ì
ëë¤.
let user1 = {
admin() {
alert("ê´ë¦¬ì ê³ì ì
ëë¤.");
}
}
let user2 = {};
user1.admin?.(); // ê´ë¦¬ì ê³ì ì
ëë¤.
user2.admin?.();
ë ìí© ëª¨ëìì user ê°ì²´ë ì¡´ì¬í기 ë문ì admin íë¡í¼í°ë .ë§ ì¬ì©í´ ì ê·¼íìµëë¤.
ê·¸ë¦¬ê³ ë í ?.()를 ì¬ì©í´ adminì ì¡´ì¬ ì¬ë¶ë¥¼ íì¸íìµëë¤. user1ì adminì´ ì ìëì´ ì기 ë문ì ë©ìëê° ì ëë¡ í¸ì¶ëììµëë¤. ë°ë©´ user2ì adminì´ ì ìëì´ ìì§ ììììë ë¶êµ¬íê³ ë©ìë를 í¸ì¶íë©´ ìë¬ ìì´ ê·¸ë¥ íê°ê° ë©ì¶ë ê²ì íì¸í ì ììµëë¤.
.ëì ëê´í¸ []를 ì¬ì©í´ ê°ì²´ íë¡í¼í°ì ì ê·¼íë ê²½ì°ì ?.[]를 ì¬ì©í ìë ììµëë¤. ì ììì ë§ì°¬ê°ì§ë¡ ?.[]를 ì¬ì©íë©´ ê°ì²´ ì¡´ì¬ ì¬ë¶ê° íì¤ì¹ ìì ê²½ì°ìë ìì íê² íë¡í¼í°ë¥¼ ì½ì ì ììµëë¤.
let user1 = {
firstName: "Violet"
};
let user2 = null; // user2ë ê¶íì´ ìë ì¬ì©ìë¼ê³ ê°ì í´ë´
ìë¤.
let key = "firstName";
alert( user1?.[key] ); // Violet
alert( user2?.[key] ); // undefined
alert( user1?.[key]?.something?.not?.existing); // undefined
?.ì deleteì ì¡°í©í´ ì¬ì©í ìë ììµëë¤.
delete user?.name; // userê° ì¡´ì¬íë©´ user.nameì ìì í©ëë¤.
?.ì ì½ê¸°ë ìì í기ìë ì¬ì©í ì ìì§ë§ ì°ê¸°ìë ì¬ì©í ì ììµëë¤.?.ì í ë¹ ì°ì°ì ì¼ìª½ìì ì¬ì©í ì ììµëë¤.
// userê° ì¡´ì¬í ê²½ì° user.nameì ê°ì ì°ë ¤ë ìëë¡ ìëì ê°ì´ ì½ë를 ìì±í´ ë³´ììµëë¤.
user?.name = "Violet"; // SyntaxError: Invalid left-hand side in assignment
// ìë¬ê° ë°ìíë ì´ì ë undefined = "Violet"ì´ ë기 ë문ì
ëë¤.
ìì½
ìµì
ë ì²´ì´ë ë¬¸ë² ?.ì ì¸ ê°ì§ ííë¡ ì¬ì©í ì ììµëë¤.
obj?.propâobjê° ì¡´ì¬íë©´obj.propì ë°ííê³ , ê·¸ë ì§ ìì¼ë©´undefined를 ë°íí¨obj?.[prop]âobjê° ì¡´ì¬íë©´obj[prop]ì ë°ííê³ , ê·¸ë ì§ ìì¼ë©´undefined를 ë°íí¨obj?.method()âobjê° ì¡´ì¬íë©´obj.method()를 í¸ì¶íê³ , ê·¸ë ì§ ìì¼ë©´undefined를 ë°íí¨
ì¬ë¬ ìì를 íµí´ ì´í´ë³´ìë¯ì´ ìµì
ë ì²´ì´ë 문ë²ì 꽤 ì§ê´ì ì´ê³ ì¬ì©í기ë ì½ìµëë¤. ?. ì¼ìª½ íê° ëìì´ nullì´ë undefinedì¸ì§ íì¸íê³ nullì´ë undefinedê° ìëë¼ë©´ íê°ë¥¼ ê³ì ì§íí©ëë¤.
?.를 ê³ì ì°ê²°í´ì ì²´ì¸ì ë§ë¤ë©´ ì¤ì²© íë¡í¼í°ë¤ì ìì íê² ì ê·¼í ì ììµëë¤.
?.ì ?.ì¼ìª½ íê°ëìì´ ìì´ë ê´ì°®ì ê²½ì°ìë§ ì íì ì¼ë¡ ì¬ì©í´ì¼ í©ëë¤.
ê¼ ìì´ì¼ íë ê°ì¸ë° ìë ê²½ì°ì ?.ì ì¬ì©íë©´ íë¡ê·¸ëë° ìë¬ë¥¼ ì½ê² ì°¾ì ì ìì¼ë¯ë¡ ì´ë° ìí©ì ë§ë¤ì§ ë§ëë¡ í©ìë¤.
ëê¸
<code>í그를, ì¬ë¬ ì¤ë¡ 구ì±ë ì½ë를 ì½ì íê³ ì¶ë¤ë©´<pre>í그를 ì´ì©íì¸ì. 10ì¤ ì´ìì ì½ëë plnkr, JSBin, codepen ë±ì ìëë°ì¤ë¥¼ ì¬ì©íì¸ì.