최근 추가됨
이것은 최근에 언어에 추가된 것입니다. 오래된 브라우저에는 폴리필이 필요할 수 있습니다.
선택적 연결 ?.
중간 속성이 없더라도 중첩된 개체 속성에 액세스하는 안전한 방법입니다.
방금 튜토리얼을 읽고 JavaScript를 배우기 시작했다면 문제가 아직 해결되지 않았을 수도 있지만 이는 매우 흔한 일입니다.
예를 들어, 사용자에 대한 정보를 보유하는 user
개체가 있다고 가정해 보겠습니다.
대부분의 사용자는 user.address
속성에 user.address.street
라는 주소가 있지만 일부는 이를 제공하지 않았습니다.
이러한 경우 user.address.street
가져오려고 할 때 사용자에게 주소가 없으면 오류가 발생합니다.
사용자 = {}로 두십시오; // "주소" 속성이 없는 사용자 경고(사용자.주소.거리); // 오류!
예상된 결과입니다. 자바스크립트는 이렇게 작동합니다. user.address
undefined
으므로 user.address.street
가져오려는 시도가 오류와 함께 실패합니다.
많은 실제 사례에서 우리는 여기서 오류(“거리 없음”을 의미) 대신 undefined
되지 않음을 선호합니다.
…그리고 또 다른 예입니다. 웹 개발에서는 document.querySelector('.elem')
과 같은 특수 메소드 호출을 사용하여 웹 페이지 요소에 해당하는 객체를 얻을 수 있으며, 그러한 요소가 없으면 null
반환합니다.
// document.querySelector('.elem')은 요소가 없으면 null입니다. let html = document.querySelector('.elem').innerHTML; // null이면 오류
다시 한 번 요소가 존재하지 않으면 null
의 .innerHTML
속성에 액세스하는 중에 오류가 발생합니다. 그리고 어떤 경우에는 요소가 없는 것이 정상적인 경우 오류를 피하고 html = null
결과로 받아들이고 싶습니다.
어떻게 할 수 있나요?
확실한 해결책은 if
또는 조건부 연산자 ?
, 해당 속성에 액세스하기 전에 다음과 같이 합니다.
사용자 = {}로 두십시오; Alert(user.address ? user.address.street : 정의되지 않음);
작동하고 오류도 없습니다… 하지만 꽤 우아하지 않습니다. 보시다시피 코드에 "user.address"
가 두 번 나타납니다.
document.querySelector
에 대한 동일한 내용은 다음과 같습니다.
html = document.querySelector('.elem') 을 허용합니까? document.querySelector('.elem').innerHTML : null;
여기서는 요소 검색 document.querySelector('.elem')
이 실제로 두 번 호출되는 것을 볼 수 있습니다. 좋지 않다.
더 깊이 중첩된 속성의 경우 더 많은 반복이 필요하므로 더욱 추악해집니다.
예를 들어 비슷한 방식으로 user.address.street.name
가져옵니다.
사용자 = {}로 두십시오; // 사용자에게 주소가 없습니다 Alert(user.address ? user.address.street ? user.address.street.name : null : null);
정말 끔찍합니다. 그러한 코드를 이해하는 데 문제가 있을 수도 있습니다.
&&
연산자를 사용하여 이를 작성하는 좀 더 좋은 방법이 있습니다.
사용자 = {}로 두십시오; // 사용자에게 주소가 없습니다 경고( user.address && user.address.street && user.address.street.name ); // 정의되지 않음(오류 없음)
속성에 대한 전체 경로를 AND로 연결하면 모든 구성 요소가 존재하게 되지만(그렇지 않은 경우 평가가 중지됨) 이상적이지도 않습니다.
보시다시피, 속성 이름은 코드에서 여전히 중복됩니다. 예를 들어 위 코드에서는 user.address
세 번 나타납니다.
이것이 선택적 연결인 이유입니다 ?.
언어에 추가되었습니다. 이 문제를 한 번에 해결하려면!
선택적 연결 ?.
?.
은 undefined
거나 null
이며 undefined
반환합니다.
이 문서의 추가 내용에서는 간결함을 위해 null
아니거나 undefined
되지 않은 경우 "존재"한다고 말할 것입니다.
즉, value?.prop
입니다.
value.prop
로 작동합니다. value
존재하면
그렇지 않은 경우( value
이 undefined/null
인 경우) undefined
반환합니다.
?를 사용하여 user.address.street
에 액세스하는 안전한 방법은 다음과 같습니다 ?.
:
사용자 = {}로 두십시오; // 사용자에게 주소가 없습니다 경고(사용자?.주소?.거리); // 정의되지 않음(오류 없음)
코드는 짧고 깔끔하며 중복이 전혀 없습니다.
document.querySelector
의 예는 다음과 같습니다.
let html = document.querySelector('.elem')?.innerHTML; // 요소가 없으면 정의되지 않습니다.
user?.address
사용하여 주소를 읽는 것은 user
개체가 존재하지 않는 경우에도 작동합니다.
사용자 = null로 둡니다. 경고(사용자?.주소); // 한정되지 않은 경고(사용자?.주소.거리); // 한정되지 않은
참고: ?.
구문은 이전 값을 선택적으로 만들지만 그 이상은 선택 사항으로 만들지 않습니다.
예를 들어 user?.address.street.name
에서 ?.
user
안전하게 null/undefined
상태로 만들 수 있지만(이 경우 undefined
반환함) user
에게만 해당됩니다. 추가 속성은 일반적인 방법으로 액세스됩니다. 그 중 일부를 선택적으로 사용하려면 more 를 교체해야 합니다 .
와 함께 ?.
.
선택적 체이닝을 남용하지 마세요
우리는 ?.
뭔가가 존재하지 않아도 괜찮은 곳에서만요.
예를 들어, 코드 논리에 따라 user
개체가 존재해야 하지만 address
는 선택 사항인 경우 user.address?.street
작성해야 하지만 user?.address?.street
작성하지 않아야 합니다.
그런 다음 user
가 정의되지 않은 경우 이에 대한 프로그래밍 오류를 확인하고 수정합니다. 그렇지 않으면 ?.
, 코딩 오류는 적절하지 않은 경우 침묵될 수 있으며 디버그하기가 더 어려워집니다.
?.
선언해야 한다
user
변수가 전혀 없으면 user?.anything
오류를 유발합니다.
// 참조 오류: 사용자가 정의되지 않았습니다. 사용자?.주소;
변수는 선언되어야 합니다(예: let/const/var user
또는 함수 매개변수로). 선택적 연결은 선언된 변수에 대해서만 작동합니다.
이전에 말했듯이, ?.
왼쪽 부분이 존재하지 않으면 평가를 즉시 중지("단락")합니다.
따라서 ?.
, 그들은 만들어지지 않을 것입니다.
예를 들어:
사용자 = null로 둡니다. x = 0이라고 하자; user?.sayHi(x++); // "user"가 없으므로 실행이 sayHi에 도달하지 않습니다. 호출 및 x++ 경고(x); // 0, 값이 증가하지 않음
선택적 연결 ?.
연산자는 아니지만 함수 및 대괄호에서도 작동하는 특수 구문 구조입니다.
예를 들어, ?.()
존재하지 않을 수 있는 함수를 호출하는 데 사용됩니다.
아래 코드에서 일부 사용자는 admin
메소드를 갖고 있고 일부는 그렇지 않습니다.
userAdmin = {를 허용하십시오. 관리자() { Alert("나는 관리자입니다"); } }; userGuest = {}를 두십시오; userAdmin.admin?.(); // 나는 관리자입니다 userGuest.admin?.(); // 아무 일도 일어나지 않습니다(해당 메소드 없음).
여기에서는 두 줄 모두 먼저 점( userAdmin.admin
)을 사용하여 admin
속성을 가져옵니다. user
개체가 존재한다고 가정하므로 안전하게 읽을 수 있기 때문입니다.
그런 다음 ?.()
왼쪽 부분을 확인합니다. admin
함수가 있으면 실행됩니다( userAdmin
의 경우도 마찬가지입니다). 그렇지 않으면( userGuest
의 경우) 오류 없이 평가가 중지됩니다.
?.[]
구문은 점 대신 속성에 액세스하기 위해 대괄호 []
사용하려는 경우에도 작동합니다 .
. 이전 사례와 마찬가지로 존재하지 않을 수도 있는 개체에서 속성을 안전하게 읽을 수 있습니다.
키 = "firstName"; 사용자1 = { 이름: "John" }; user2 = null로 둡니다. 경고( user1?.[키] ); // 존 경고( user2?.[키] ); // 한정되지 않은
또한 ?.
delete
:
사용자 삭제?.이름; // 사용자가 존재하면 user.name을 삭제합니다.
우리는 ?.
안전하게 읽고 삭제하기 위해(쓰기는 안 됨)
선택적 연결 ?.
과제의 왼쪽에는 아무 소용이 없습니다.
예를 들어:
사용자 = null로 둡니다. user?.name = "John"; // 오류, 작동하지 않습니다 // 다음과 같이 평가되기 때문입니다: 정의되지 않음 = "John"
선택적 연결 ?.
구문에는 세 가지 형식이 있습니다.
obj?.prop
– obj
존재하는 경우 obj.prop
반환하고, 그렇지 않으면 undefined
반환합니다.
obj?.[prop]
– obj
존재하는 경우 obj[prop]
반환하고, 그렇지 않으면 undefined
반환합니다.
obj.method?.()
– obj.method
존재하는 경우 obj.method()
호출하고, 그렇지 않으면 undefined
반환합니다.
보시다시피, 모두 간단하고 사용하기 쉽습니다. ?.
왼쪽 부분에서 null/undefined
있는지 확인하고 그렇지 않은 경우 평가를 진행할 수 있습니다.
?.
중첩된 속성에 안전하게 액세스할 수 있습니다.
그래도 신청해야겠죠 ?.
코드 논리에 따라 왼쪽 부분이 존재하지 않는 것이 허용되는 경우에만 주의 깊게 살펴보세요. 프로그래밍 오류가 발생하더라도 우리에게 숨겨지지 않도록 하기 위함입니다.