티스토리 뷰
4.6 Optional chaining '?.'
종종 어떤 값을 가져오려 할 때, 해당 값이 존재하지 않는 경우가 있다.
let user = {}; // a user without "address" property
alert(user.address.street); // Error!
이 경우 에러를 뱉는 것보다, undefined와 같은 값이 반환되는 것이 좋을 것 같다.
let user = {};
alert(user.address ? user.address.street : undefined);
// ---------------------------------
let user = {}; // user has no address
alert(user.address ? user.address.street ? user.address.street.name : null : null)
위와 같이 해당 값의 존재여부를 체크하고 undefined를 반환하도록 할 수 있지만, 같은 구문이 반복되기도 하고 보기가 좋지는 않다. 이럴 때 사용하는 것이 optional chainig이다.
Optional chaining
let user = {}; // user has no address
alert( user?.address?.street ); // undefined (no error)
user가 존재 => user.address 접근, user.address가 존재 => user.address.street로 접근한다. 만약 중간에 값이 없는(null이나 undefined) 경우 undefined를 반환한다.
만약 아래처럼 일부 대상에게만 있다면 해당 대상에게만 적용된다.
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
위 예시처럼, optional chaining이 유용하긴하지만 비즈니스적으로 optional한 대상에 한해 사용하는 것이 적절해보인다. 값이 무조건 존재해야하는 대상인데 없는 경우라면, undefined를 반환하기보다 에러를 뱉는 것이 어쩌면 더 바람직할 수 있기 때문이다.
Other variants: ?.(), ?.[]
아래와 같이 함수 존재여부, 변수 속성 존재 여부, 삭제 전 존재여부를 판별할 때도 사용될 수 있다.
let userAdmin = {
admin() {
alert("I am admin");
}
};
let userGuest = {};
userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // nothing happens (no such method)
// -----------------------------
let key = "firstName";
let user1 = {
firstName: "John"
};
let user2 = null;
alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined
// -----------------------------
delete user?.name; // delete user.name if user
하지만, 값을 새롭게 할당하는 작업에는 사용할 수 없다.
let user = null;
user?.name = "John"; // Error, doesn't work
// because it evaluates to: undefined = "John"
4.7 symbols
객체 속성의 키는 string, symbol 타입만이 가능하다. symbol 타입은 아래와 같이 생성 가능하다. 고유한 식별자로서 역할을 하기 때문에, 같은 이름으로 symbol을 생성하더라도 서로 다른 객체로 취급한다.
// id is a symbol with the description "id"
let id = Symbol("id");
// --------------
let id1 = Symbol("id");
let id2 = Symbol("id");
alert(id1 == id2); // false
또한, symbol은 자동으로 string으로 형변환되지 않는다.
symbol을 생성 후 alert 함수로 symbol을 출력하려해도 문자열로 변환되지 않기 때문에 에러가 발생한다. 필요하다면 .toString()을 사용해야 한다.
"Hidden" properties
let user = { // belongs to another code
name: "John"
};
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // we can access the data using the symbol as the key
symbol 타입은 우연히 접근하거나 덮어쓸 수 없는 숨겨진 객체를 만들 수 있다. 위 예시를 보면 user 객체의 id로 symbol 타입을 사용했다. 해당 속성이 쉽게 변경될 수 없도록 symbol로 생성한 것이다.
symbols in an object literal
symbol로 이루어진 속성은 반복문이나, Object.keys(user)와 같은 함수를 통해서도 접근할 수 없다.
Global symbols
보통 같은이름의 symbol이어도 다른 것으로 취급하지만, 원한다면 같은 이름을 가지면 같은 symbol 취급을 하도록 만들 수 있다. (아래 코드 참조)
// read from the global registry
let id = Symbol.for("id"); // if the symbol did not exist, it is created
// read it again (maybe from another part of the code)
let idAgain = Symbol.for("id");
// the same symbol
alert( id === idAgain ); // true
Symbol.keyFor
아래 방식으로 symbol의 이름을 반환한다. 다만, global symbol이 아닌 경우 동작하지 않는다.
/ get symbol by name
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");
// get name by symbol
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id
// ------------------------------
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");
alert( Symbol.keyFor(globalSymbol) ); // name, global symbol
alert( Symbol.keyFor(localSymbol) ); // undefined, not global
alert( localSymbol.description ); // name
System symbols
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.iterator
- Symbol.toPrimitive
위 System symbol 들은 자주 쓰인다고 한다. 참고로 기억해 두자.
'스터디 > JavaScript' 카테고리의 다른 글
모던 자바스크립트 튜토리얼 part1 - 5.1 ~ 2 (0) | 2024.05.17 |
---|---|
모던 자바스크립트 튜토리얼 part1 - 4.8 (0) | 2024.05.17 |
모던 자바스크립트 튜토리얼 par1 - 4.4 ~ 5 (0) | 2024.05.16 |
모던 자바스크립트 튜토리얼 part1 - 4.3 (0) | 2024.05.16 |
모던 자바스크립트 튜토리얼 part1 - 4.2 (0) | 2024.05.16 |