[1] Optional Chaining 연산자 → "?."
optional chaining 연산자는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있다.
const obj = {
a: {
b: {
c: {
age: 12
}
}
}
}
console.log(obj.a.b.c.age); // 12
이렇게 nesting 이 된 객체에서 만약 age 의 값을 읽으려고 했을때 c 프로퍼티 바로 위 단계인 b 가 없는데 위와 같이 읽으려고 한다면? "Cannot read properties of undefined" 에러가 출력된다.
여기서 optional chaining 연산자의 진가를 볼 수 잇는데,
console.log(obj.a?.c?.d?.age); // 12
우선 사용법은 위와 같다. "?." 연산자가 사용된 왼쪽 부터, 만약 a 가 있다면 후속적으로 만약 b 가 있다면... 이런식으로 고리(chaining) 처럼 위에서 부터 아래로 접근할 수가 있다.
- 함수의 호출과 Optional Chaining
존재하지 않을 수 있는 매서드를 호출할 때, optional chaining을 사용할 수 있다. 예를 들어, 구현 기간이나 사용자 장치에서 사용할 수 없는 기능 때문에 메서드를 사용할 수 없는 API를 사용할 경우, 유용할 수 있다.
함수 호출과 optional chaining을 사용함으로써 메서드를 찾을 수 없는 경우에 예외를 발생시키는 것 대신에 그 표현식은 자동으로 undefined를 반환한다.
function doSomething(onContent, onError) {
try {
// ... do something with the data
}
catch (err) {
if (onError) { // Testing if onError really exists
onError(err.message);
}
}
}
// Using optional chaining with function calls
function doSomething(onContent, onError) {
try {
// ... do something with the data
}
catch (err) {
onError?.(err.message); // no exception if onError is undefined
}
}
[2] 널 병합 연산자 Nullish coalescing → "??"
널 병합 연산자(??) 는 왼쪽 피연산자가 null 또는 undefined일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환하는 논리 연산자이다.
널 병합 연산자는 연산자 우선 순위가 다섯번째로 낮은데, || 의 바로 아래이며 조건부 연산자(삼항연산자)의 바로 위이다.
- 왼쪽아니면 오른쪽
?? 와 || 는 왼쪽의 피연산자의 값에 따라 그대로 왼쪽 값을 사용할 것인지 아니면 오른쪽 값을 사용할 것인지 결정해주는 역할은 같다.
- || 와 ?? 의 차이점은...
// OR 연산자
let resultA = null || 1;
console.log(result); // output: 1
resultA = 0 || 1;
console.log(result); // output: 1
// ?? 연산자
let resultB = null ?? 1;
console.log(resultB); // output: 1
resultB = 0 ?? 1;
console.log(resultB); // output: 0
OR 연산자의 경우 숫자 0을 null 또는 undefined 로 판단하여 오른쪽 값을 변수에 할당한다.
반대로 널 병합 연산자의 경우 0 을 변수에 할당하는 것을 볼 수 있다.
학생의 점수를 담고 있는 데이터베이스에서 A 학생이 0 이라는 점수를 실제로 가지고 있는 것과, 아직 점수가 채점되지 않아 NULL 의 데이터를 담고있을때 OR 연산자를 사용하면 코드를 실행하는데 있어 논리적인 오류가 발생한다.
점수가 0 이면 0을 가져와 활용하면 되고, 만약 NULL 이면 "점수가 아직 채점되지 않았습니다." 처럼 처리될 수 있을 것이다. 그렇기 때문에 숫자를 활용해야만 하는 상황에서는 OR 연산자가 적합하지 않다고 생각한다.
- 연산자의 우선순위
연산자를 다룰때 또 하나 중요한 점은 바로 우선순위 이다. 덥셈, 곱셈, 뺄셈, 나눗셈 과 같은 연산자에서 우선순위에 대한 개념은 알고 있다. 예를 들어 1 + 2 * 2 의 경우 덧셈 보다 곱셈이 우선순위를 가진다. 만약 내가 원하는 결과가 5 라면, 소괄호를 써서 2 * 2를 묶어주면 된다. 5가 아닌 6을 생각했다면 위 식 그대로 써도 될것이다.
자바스크립트는 정말 다양한 연산자를 가지고 있는데, 그 것들 모두 우선순위를 가지고 있다. 그렇다면 OR 연산자와 널 병합 연산자의 우선순위는 어떻게 될까. OR 연산자가 널 병합 연산자 보다 우선순위를 가지고 있다.
OR 연산자와 널 병합 연산자를 같이 활용하는 상황이 있다면 그 우선순위를 이해하고 사용해야한다.
아래 샘플코드를 보면 나는 result 변수에 "Hello" 라는 문자열 값을 할당하고 싶었다. 두 개의 예제를 보면, 결과적으로 "Hello" 를 변수에 담기는 했으나 연산자의 처리 과정이 다른 것을 볼 수 있다.
이렇게 숫자를 다루는 계산식에서의 연산자는 일상생활에서도 많이 쓰지만 논리식에서 사용하는 연산자는 생소하여 글을 써보았다.
// Example with logical OR (||) and nullish coalescing (??)
const a = null;
const b = "Hello";
const c = 0;
const d = "World";
// Operator precedence without parentheses
const result1 = a ?? b || c ?? d;
console.log(result1); // Expected output: "Hello"
// Explanation:
// Step-by-step evaluation due to precedence rules:
// 1. a ?? b -> null ?? "Hello" -> "Hello" (nullish coalescing)
// 2. "Hello" || c -> "Hello" || 0 -> "Hello" (logical OR)
// 3. "Hello" ?? d -> "Hello" ?? "World" -> "Hello" (nullish coalescing)
// Using parentheses to control precedence
const result2 = (a ?? b) || (c ?? d);
console.log(result2); // Expected output: "Hello"
// Explanation:
// Step-by-step evaluation due to parentheses:
// 1. (a ?? b) -> (null ?? "Hello") -> "Hello" (nullish coalescing)
// 2. (c ?? d) -> (0 ?? "World") -> 0 (nullish coalescing)
// 3. "Hello" || 0 -> "Hello" (logical OR)
'자바스크립트' 카테고리의 다른 글
Deep, Shallow comparison (깊은, 얕은 비교 / mutable, immutable) (0) | 2022.09.22 |
---|---|
함수의 매개변수(parameter) 종류 (0) | 2022.07.14 |
함수의 활용 (0) | 2022.05.11 |
event handling, 이벤트 처리 (0) | 2022.04.02 |
마우스 포인터 좌표, 마우스 위치 값 확인 (0) | 2022.04.02 |
댓글