표현식 (expression)은 값으로 평가될 수 있는 문이다. 즉 결과가 값인 문과, 표현식이 아닌 문의 차이를 이해하는 것이 매우 중요하다. 이 차이를 이해해야만 자바스크립트의 요소들을 효과적으로 조합할 수 있다.
표현식이 아닌 문(statement)은 일종의 지시라고 생각할 수 있고, 표현식은 무언가를 요청하는 것이라고 생각할 수 있습니다. 표현식은 값이 되고 그 결과를 다른 표현식에서 결합해 다른 값을 얻을 수 있다. 표현식이 아닌 문은 이런 식으로 결합할 수 없다.
표현식은 값이 되므로 할당에 쓸 수 있다. 즉, 표현식의 결과를 변수나 상수, 프로퍼티에 할당할 수 있다.
곱셈은 표현식이다.
let x, y;
y = x = 3 * 5;
x와 y 두 변수가 있고 값은 모두 15이다. 이것이 가능한 것은 곱셈과 할당이 모두 표현식이기 때문이다. 자바스크립트는 이렇게 표현식이 결합된 것을 보면 쪼갤 수 있는 만큼 쪼개서 한 부분씩 실행합니다.
자바스크립트가 표현식을 평가하는 순서를 연산자 우선순위라 부르며, 표현식은 대부분 연산자 표현식이다. 즉 곱셈 표현식은 곱셈 연산자 (*) 와 피연산자 (operand) 두 개로 이루어진다.
연산자를 표현식의 '명사'에 대한 '동사'라고 생각하면 좋다. 표현식이 값이 되는 것이라면 연산자는 값을 만드는 행동이라는 뜻이다.
자바스크립트의 산술 연산자
연산자 우선순위를 이해해야 자바스크립트 프로그램이 어떻게 동작하는지 이해할 수 있다.
8 / 2 + 3 * (4 * 2 - 1)
= 25
괄호가 제일 먼저 계산되고, 그다음 곱셈 나눗셈, 마지막으로 덧셈 뺄샘으로 계산된다.
산수에서만 쓰이는 것은 아니고 자바스크립트는 표현식을 평가할 때도 비슷하게 규칙을 적용한다.
let x = 3, y;
x += y = 6*5/2;
// x = 18
// y = 15
비교 연산자는 두 개의 값을 비교한다. 크게 말해 비교 연산자는 세 가지 타입으로 나뉜다.
일치함은 두 값이 같은 객체를 가리키거나, 같은 타입이고 값도 같다면 이 값을 일치한다고 합니다.
두 값이 일치하는지 확인할 때는 === 연산자를 쓰거나 그 반대인 !== 연산자를 쓴다.
동등함은 두 값이 같은 객체를 가리키거나 같은 값을 갖도록 변환할 수 있다면 두 값을 동등하다고 한다.
앞 부분은 괜찮지만 두 번째 부분은 수많은 골칫거리와 혼란을 발생시킨다. 문자열 "33"은 숫자 33으로 변환할 수 있으므로 이 둘은 동등하다. 하지만 타입이 다르므로 일치하지는 않는다.
const n = 5;
const s = '5';
n === s // false 타입이 다르다.
n !== s // true
n === Number(s) // true
n == s // true 권장하지 않음
n != s // false 권장하지 않음
관계 연산자에는 작다 < , 작거나 같다 <= , 크다 > , 크거나 같다 >= 네 가지가 있다.
숫자를 비교할 때는 염두에 두어야 할 것이 있다.
특별한 숫자형 값 NaN은 그 자신을 포함하여 무엇과도 같지 않다. 즉, NaN === NaN 은 false이다.
숫자가 NaN인지 알아보려면 내장된 isNaN 함수를 사용하면 된다.
자바스크립트의 숫자는 모두 더블 형식이다. 더블 형식은 근사치이므로, 자바스크립트에서 숫자를 비교하다 보면 예상 외의 결과가 나타날 수 있다.
let n = 0;
white(true) {
n += 0.1;
if(n === 0.3) break;
}
console.log(n);
이 루프는 0.3에서 멈추지 않고 그 값을 살짝 피한 다음 영원히 실행된다.
이 결과는 0.1이 더블 형식으로 정확히 나타낼 수 없는 값이기 때문인데 0.1은 이진 표현으로 나타낼 수 있는 숫자들 사이에 걸쳐 있다. 따라서 이 루프를 세 번째 반복할 때의 n의 값은 0.3000000000000004이므로 테스트는 false이고, 종료 조건이 실패한다.
Number.EPSILION과 관계 연산자를 사용해서 '느슨하게' 비교하고 성공적으로 루프를 빠져나갈 수 있다.
let n = 0;
white(true) {
n += 0.1;
if(Math.abs(n - 0.3) < Number.EPSILION) break;
}
console.log(n);
테스트하는 숫자 n에서 비교 대상(0.3)을 뺀 다음 절댓값을 취하는 방식이다.
여기서 사용한 방법은 두 개의 더블 형식이 같다고 할 수 있을 만큼 가까운 숫자인지 판단할 때 일반적으로 사용하는 방법입니다.
자바스크립트에서 + 연산자는 덧셈과 문자열 병합에 모두 사용된다.
피연산자의 타입을을 왼쪽에서 오른쪽으로 평가 후 덧셈을 할지 문자열 병합을 할지 판단하고, 피연산자중 하나라도 문자열이면 문자열 병합을 수행한다.
3 + 5 + "8" // 문자열 '88'
'3' + 5 + 8 //문자열 '358'
논리 연산자는 불리언 값만 다룰 수 있으며 불리언에는 false / true 두개의 값이 있다.
자바스크립트는 모든 데이터 타입을 참 같은 값과 거짓 같은 값으로 나눌 수 있다.
거짓 같은 값
이 외의 값은 모두 참 같은 값이다. 굉장히 많이 존재하지만 몇가지 염두에 두어야 한다.
ES6에서 새로 도입된 비구조화 할당은 객체나 배열을 변수로 해채할 수 있다.
const obj = { b: 2, c: 3, d: 4 }
// 비구조화
const { a, b, c } = obj;
a // undefined: obj에는 "a"는 정의되지 않았습니다.
b // 2
c // 3
f // ReferenceError: "f"는 정의되지 않았습니다.
객체를 해체할 때는 반드시 변수 이름과 객체의 프로퍼티 이름이 일치해야한다.
if...else 문을 3항 연산자로 바꾸기
if(isPrime(n)) {
label = 'prime';
} else {
label = 'non-prime';
}
위 코드를 3항 연산자로 바꾸면 코드가 간결해지고 읽기 쉬워진다.
label = isPrime(n) ? 'prime' : 'non-prime';
if 문을 단축 평가하는 OR 표현식으로 바꾸기
if(!options) options = {};
위 코드를 OR 표현식으로 바꿔 간결하게 줄일 수 있다.
options = options || {};
이 연산자들은 데이터를 조작하는 가장 기본적인 방법이다. 비트 연산자처럼 거의 사용하지 않는 연산자도 있고, 점 연산자처럼 연산자라는 생각이 들지 않는 연산자도 있다.
할당, 산술, 비교, 불리언 연산자는 가장 널리 쓰이는 연산자이므로 잘 이해하고 있어야 한다.