ãªãã·ã§ãã«ãã§ã¼ã³æ¼ç®å (?.)
Baseline
åºãå©ç¨å¯è½
ãã®æ©è½ã¯åºãå®è£ ããã¦ãããå¤ãã®ãã¼ã¸ã§ã³ã®ç«¯æ«ããã©ã¦ã¶ã¼ã§åä½ãã¾ãã2020å¹´7æä»¥éããã¹ã¦ã®ãã©ã¦ã¶ã¼ã§å©ç¨å¯è½ã§ãã
ãªãã·ã§ãã«ãã§ã¼ã³æ¼ç®å (?.) (optional chaining) ã¯ããªãã¸ã§ã¯ãã®ããããã£ã«ã¢ã¯ã»ã¹ãããã颿°ãå¼ã³åºããããã¾ãããã®æ¼ç®åã使ç¨ãã¦ã¢ã¯ã»ã¹ãããªãã¸ã§ã¯ãã¾ãã¯å¼ã³åºããã颿°ã undefined ã¾ã㯠null ã®å ´åãã¨ã©ã¼ãçºçãããã¨ãªããå¼ãéä¸ã§çµäºããundefined ã¨è©ä¾¡ããã¾ãã
試ãã¦ã¿ã¾ããã
const adventurer = {
name: "Alice",
cat: {
name: "Dinah",
},
};
const dogName = adventurer.dog?.name;
console.log(dogName);
// äºæ³ãããçµæ: undefined
console.log(adventurer.someNonExistentMethod?.());
// äºæ³ãããçµæ: undefined
æ§æ
obj?.prop
obj?.[expr]
func?.(args)
解説
?. æ¼ç®åã®æ©è½ã¯ . ãã§ã¼ã³æ¼ç®åã¨ä¼¼ã¦ãã¾ãããåç
§ããã«å¤ï¼null ã¾ã㯠undefinedï¼ã®å ´åã«ã¨ã©ã¼ã¨ãªãã®ã§ã¯ãªããå¼ãç絡ãã undefined ãè¿ãããã¨ãããç°ãªãã¾ãã颿°å¼ã³åºãã§ä½¿ç¨ããã¨ãä¸ãããã颿°ãåå¨ããªãå ´åã undefined ãè¿ãã¾ãã
ããã¯ãåç §ã失ãããå¯è½æ§ã®ããé£çµãããããããã£ã«ã¢ã¯ã»ã¹ããæãçµæçã«çãåç´ãªå¼ã«ãªãã¾ããã¾ããå¿ è¦ãªããããã£ã®åå¨ãä¿è¨¼ããã¦ããªãå ´åã«ãªãã¸ã§ã¯ãã®ã³ã³ãã³ããæ¢ç´¢ããã®ã«ãå½¹ç«ã¡ã¾ãã
ãã¨ãã°ãå
¥ãåæ§é ãæã¤ãªãã¸ã§ã¯ã obj ãèãã¾ãããããªãã·ã§ãã«ãã§ã¼ã³æ¼ç®åãªãã§æ·±ãå
¥ãåã«ãªã£ããµãããããã£ã«ã¢ã¯ã»ã¹ããã«ã¯ã次ã®ããã«ãåããããã£éã®åç
§ã確èªããå¿
è¦ãããã¾ãã
const nestedProp = obj.first && obj.first.second;
obj.first ã®å¤ã null ã§ã¯ãªãï¼ãã㦠undefined ã§ããªãï¼ãã¨ã確èªãããå¾ã§ãobj.first.second ã®å¤ã«ã¢ã¯ã»ã¹ãã¾ããããã«ãããobj.first ããã¹ãããã«ç´æ¥ obj.first.second ã«ã¢ã¯ã»ã¹ããå ´åã«çºçããã¨ã©ã¼ãé²ããã¨ãã§ãã¾ãã
ãã㯠JavaScript ã§ãã使ããããã¿ã¼ã³ã§ããããã§ã¼ã³ãé·ããªãã¨åé·ã«ãªããå®å
¨ã§ã¯ããã¾ãããä¾ãã°ãobj.first ãå½å¤ã§ãnull ã undefined ã§ã¯ãªãå¤ï¼ä¾ãã° 0ï¼ã§ãã£ãå ´åãããã§ãç絡ã¨ãªããnestedProp ã 0 ã«ãªãã¾ããããã¯æã¾ãããªãããããã¾ããã
ãããããªãã·ã§ãã«ãã§ã¼ã³æ¼ç®å (?.) ã使ãã°ãobj.first.second ã«ã¢ã¯ã»ã¹ãããã¨ããåã« obj.first ã®ç¶æ
ãæç¤ºçã«ãã¹ãããå¿
è¦ããªããªãã¾ãã
const nestedProp = obj.first?.second;
?. ã . ã®ä»£ããã«ç¨ãããã¨ã§ã JavaScript ã obj.first.second ã«ã¢ã¯ã»ã¹ãããã¨ããåã« obj.first ã null ã¾ã㯠undefined ã§ãªããã¨ãæé»çã«ç¢ºãããããã«ãªãã¾ããobj.first ã null ã¾ã㯠undefined ã§ãã£ãå ´åãå¼ãèªåçã«ç絡ããã undefined ãè¿ãã¾ãã
ããã¯ã䏿çãªå¤æ°ã使ãããªããã¨ãé¤ããæ¬¡ã®å¼ã¨ç価ã§ãã
const temp = obj.first;
const nestedProp =
temp === null || temp === undefined ? undefined : temp.second;
ãªãã·ã§ãã«ãã§ã¼ã³ã¯ã宣è¨ããã¦ããªãã«ã¼ããªãã¸ã§ã¯ãã§ã¯ä½¿ç¨ã§ãã¾ããããå¤ã undefined ã®ã«ã¼ããªãã¸ã§ã¯ãã§ã¯ä½¿ç¨ãããã¨ãã§ãã¾ãã
undeclaredVar?.prop; // ReferenceError: undeclaredVar is not defined
颿°å¼ã³åºãã«ããããªãã·ã§ãã«ãã§ã¼ã³æ¼ç®å
åå¨ããªãå¯è½æ§ããã颿°ã®å¼ã³åºãã試è¡ããã¨ãã«ããªãã·ã§ãã«ãã§ã¼ã³ã使ããã¨ãã§ãã¾ããããã¯ãã¨ãã°ãã¦ã¼ã¶ã¼ã®ç«¯æ«ä¸ã§ä½¿ããªãã£ãããå®è£ ãå¤ãã£ããããããã«ä½¿ããªãã£ããããå¯è½æ§ããã API ã使ãã¨ãã«å½¹ç«ã¡ã¾ãã
颿°å¼ã³åºãã§ãªãã·ã§ãã«ãã§ã¼ã³æ¼ç®åãç¨ããå ´åãã¡ã½ãããè¦ã¤ãããªãã¨ãã¯èªåçã« undefined ãè¿ããä¾å¤ã¯çºçãã¾ããã
const result = someInterface.customMethod?.();
ãããããã®ãããªååã®ããããã£ã颿°ã§ãªãå ´åã?. ã使ç¨ãã¦ããTypeError ä¾å¤ "someInterface.customMethod is not a function" ãçºçãã¾ãã
ã¡ã¢:
颿°ã§ã¯ãªãååã®ããããã£ããã£ãå ´åã ?. ã使ç¨ãã㨠TypeError ä¾å¤ãçºçãã¾ã ("someInterface is null")ã
ãã someInterface èªä½ã null ã¾ã㯠undefined ã§ããå¯è½æ§ãããå ´åã¯ããã®ä½ç½®ã«ã ?. ã使ç¨ããå¿
è¦ãããã¾ããã¤ã¾ããsomeInterface?.customMethod?.() ã®ããã«æå®ãã¾ãã
eval?.() ã¯éæ¥ç eval ã¢ã¼ãã«å
¥ãããã®æçã®æ¹æ³ã§ãã
ãªãã·ã§ãã«ãã§ã¼ã³æ¼ç®åã¨å¼ã®çµã¿åãã
ãã©ã±ããè¨æ³ã使ç¨ãã¦å¼ã®ããããã£ã«ã¢ã¯ã»ã¹ããéã«ãããªãã·ã§ãã«ãã§ã¼ã³æ¼ç®åã使ç¨ãããã¨ãã§ãã¾ãã
const propName = "x";
const nestedProp = obj?.[propName];
ããã¯é åã®æ·»åã§ã¢ã¯ã»ã¹ããéã«è§æ¬å¼§ã使ç¨ããå¿ è¦ããããããé åã«å¯¾ãã¦ç¹ã«æçãªæ©è½ã§ãã
function printMagicIndex(arr) {
console.log(arr?.[42]);
}
printMagicIndex([0, 1, 2, 3, 4, 5]); // undefined
printMagicIndex(); // undefined; if not using ?., this would throw an error: "Cannot read properties of undefined (reading '42')"
ç¡å¹ãªãªãã·ã§ãã«ãã§ã¼ã³
ãªãã·ã§ãã«ãã§ã¼ã³å¼ã®è©ä¾¡çµæã«å¤ãä»£å ¥ãããã¨ãããã¨ã¯ä¸æ£ãªå¦çã§ãã
const object = {};
object?.property = 1; // SyntaxError: Invalid left-hand side in assignment
ãã³ãã¬ã¼ããªãã©ã«ã¿ã°ã¯ãªãã·ã§ãã«ãã§ã¼ã³ã«ã¯ã§ãã¾ããï¼SyntaxError: tagged template cannot be used with optional chainãåç §ï¼ã
String?.raw`Hello, world!`;
String.raw?.`Hello, world!`; // SyntaxError: Invalid tagged template on optional chain
new å¼ã®ã³ã³ã¹ãã©ã¯ã¿ã¼ã¯ãªãã·ã§ãã«ãã§ã¼ã³ã使ç¨ã§ãã¾ããï¼SyntaxError: new keyword cannot be used with an optional chain ãåç
§ï¼ã
new Intl?.DateTimeFormat(); // SyntaxError: Invalid optional chain from new expression
new Map?.();
ç絡è©ä¾¡
ãªãã·ã§ãã«ãã§ã¼ã³å¼ã使ç¨ããå ´åãå·¦ãªãã©ã³ãã null ã¾ã㯠undefined ã®å ´åããã®å¼ã¯è©ä¾¡ããã¾ãããä¾ãã°æ¬¡ã®ããã«ãªãã¾ãã
const potentiallyNullObj = null;
let x = 0;
const prop = potentiallyNullObj?.[x++];
console.log(x); // x ãã¤ã³ã¯ãªã¡ã³ãããã¦ããªãã®ã§ 0
ãã®å¾ã®ããããã£ã¸ã®ã¢ã¯ã»ã¹ãè©ä¾¡ããã¾ããã
const potentiallyNullObj = null;
const prop = potentiallyNullObj?.a.b;
// ããã¯ã¨ã©ã¼ãçºçãã¾ãããæåã®ãªãã·ã§ãã«ãã§ã¼ã³ã§è©ä¾¡ããã§ã«åæ¢ãã¦ããããã§ãã
ããã¯ä¸è¨ã®ãã®ã¨ç価ã§ãã
const potentiallyNullObj = null;
const prop =
potentiallyNullObj === null || potentiallyNullObj === undefined
? undefined
: potentiallyNullObj.a.b;
ãã ãããã®ç絡è©ä¾¡ã®åä½ã¯ãããããã£ã«ã¢ã¯ã»ã¹ããä¸é£ã®ããã§ã¼ã³ããé£ç¶ãã¦è¡ãå ´åã®ã¿çºçãã¾ãã ãã§ã¼ã³ã®ä¸é¨ãã°ã«ã¼ãåãã¦ãããã®å¾ã®ããããã£ã¸ã®ã¢ã¯ã»ã¹ã¯å¼ãç¶ãè©ä¾¡ããã¾ãã
const potentiallyNullObj = null;
const prop = (potentiallyNullObj?.a).b;
// TypeError: Cannot read properties of undefined (reading 'b')
ããã¯ä¸è¨ã®ãã®ã¨ç価ã§ãã
const potentiallyNullObj = null;
const temp = potentiallyNullObj?.a;
const prop = temp.b;
ãã ããtemp 夿°ã¯ä½æããã¾ããã
ä¾
>åºæ¬çãªä¾
次ã®ä¾ã§ã¯ããããã«åå¨ããªã CSS ã¡ã³ãã¼ã® name ããããã£ãåå¾ãããã¨ãã¦ãã¾ãããããã£ã¦ãçµæã¯ undefined ã«ãªãã¾ãã
const myMap = new Map();
myMap.set("JS", { name: "Josh", desc: "I maintain things" });
const nameBar = myMap.get("CSS")?.name;
ãªãã·ã§ã³ã®ã³ã¼ã«ããã¯ãã¤ãã³ããã³ãã©ã¼ã®æ±ã
ã³ã¼ã«ããã¯ããªãã¸ã§ã¯ãããã®ãã§ããã¡ã½ãããæ§é åè§£ãã¿ã¼ã³ã§ä½¿ç¨ããå ´åãåå¨ããªãå¤ãæã¤å¯è½æ§ãããããããã®åå¨ãæ¤æ»ããªãéãããã®å¤ã颿°ã¨ãã¦å¼ã³åºããã¨ã¯ã§ãã¾ããã?. ã使ç¨ããã¨ããã®ä½åãªæ¤æ»ãé¿ãããã¨ãã§ãã¾ãã
// ãªãã·ã§ãã«ãã§ã¼ã³ãªãã§æ¸ãããã³ã¼ã
function doSomething(onContent, onError) {
try {
// ãã¼ã¿ã§ä½ããè¡ã
} catch (err) {
// onError ãæ¬å½ã«åå¨ãããã©ããã確èª
if (onError) {
onError(err.message);
}
}
}
// 颿°å¼ã³åºãã§ãªãã·ã§ãã«ãã§ã¼ã³ã使ç¨
function doSomething(onContent, onError) {
try {
// ãã¼ã¿ã§ä½ããè¡ã
} catch (err) {
onError?.(err.message); // onError ãå®ç¾©ããã¦ããªãå ´åã¯ä¾å¤ãªã
}
}
ãªãã·ã§ãã«ãã§ã¼ã³ãã¤ãªãã¦ä½¿ã
å ¥ãåã«ãªã£ããªãã¸ã§ã¯ãã§ã¯ããªãã·ã§ãã«ãã§ã¼ã³æ¼ç®åãä½åº¦ã§ã使ããã¨ãã§ãã¾ãã
const customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls", // 詳細ãªä½æã¯ä¸æ
},
};
const customerCity = customer.details?.address?.city;
// ããã¯ãªãã·ã§ãã«ãã§ã¼ã³ã®é¢æ°å¼ã³åºãã§ãåä½ãã¾ã
const customerName = customer.name?.getName?.(); // ã¡ã½ãããåå¨ããªãã®ã§ã customerName 㯠undefined
ãã«å¤å使¼ç®åã¨å ±ã«ä½¿ã
ãã«å¤å使¼ç®åããªãã·ã§ãã«ãã§ã¼ã³ã®å¾ã«ã¤ãããã¨ã§ãå¤ãåå¨ããªãã£ãã¨ãã®æ¢å®å¤ãæå®ãããã¨ãã§ãã¾ãã
function printCustomerCity(customer) {
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity);
}
printCustomerCity({
name: "Nathan",
city: "Paris",
}); // "Paris"
printCustomerCity({
name: "Carl",
details: { age: 82 },
}); // "Unknown city"
仿§æ¸
| 仿§æ¸ |
|---|
| ECMAScript® 2027 Language Specification > # prod-OptionalExpression > |