연산자란 문장 부호 혹은 영어, 숫자로 구성된 예약된 구문입니다.
+
라는 기호는 숫자를 추가하거나 문자열을 연결할 수 있게 하고, <
기호는 좌항과 우항의 값을 비교합니다.
이러한 연산자는 여러 종류로 분류할 수 있습니다.
연산이라고 하면 가장 먼저 사칙연산이 떠오릅니다. 자바스크립트 또한 이런 산술적인 연산을 제공합니다. 사칙연산은 우리가 흔히 아는 기호(+, -, *, /)와 동일하게 움직입니다.
산술 연산자는 2가지로 나뉩니다.
이항이라는 말은 항이 2개가 있다는 의미입니다. x + y
는 연산되는 대상인 피연산자가 2개이죠? 그래서 이항(binary) 산술 연산자입니다.
연산자 | 동작 |
---|---|
+ | 덧셈 |
- | 뺄셈 |
* | 곱셈 |
/ | 나눗셈 |
% | 나머지 |
5 + 2 // 7
5 - 2 // 3
5 * 2 // 10
5 / 2 // 2.5
5 % 2 // 1
이항 연산자와 달리 단항 산술 연산자는 1개의 피연산자만이 존재합니다.
조금 낯선 모양일 수 있습니다.
연산자 | 동작 | 부수효과 |
---|---|---|
++ | 증가 | 피연산자의 값을 변경 |
-- | 감소 | 피연산자의 값을 변경 |
+ | 숫자타입에는 효과없음. 숫자타입으로 변환될 수 있는 경우 변환된 값 반환 |
|
- | 양수를 음수로, 음수를 양수로 반전 | X |
let x = 1
x++ // 2
x-- // 1
console.log(-x) // -1
여기서 증가/감소 연산자는 피연산자의 앞에 붙는지, 뒤에 붙는지에 따라 동작하는 시점에 차이가 있습니다.
let x = 10
let result
// 선할당 후증가(postfix increment operator)
result = x++
console.log(result, x) // 10, 11
// 선증가 후할당(prefix increment operator)
result = ++x
console.log(result, x) // 12 12
// 선할당 후감소(postfix decrement operator)
result = x--
console.log(result, x) // 12 11
// 선감소 후할당(prefix decrement operator)
result = --x
console.log(result, x) // 10 10
조금 복잡하죠? 사실 저는 이런 증가/감소 단항 연산자는 잘 사용하지 않습니다. 잘못된 연산이 될 수도 있고, 처음 값을 할당한 변수의 값이 계속 바뀌기 때문이죠. 그래서 아래와 같은 방식을 추천합니다.
let x = 10
let result
result = x + 1
console.log(result, x) // 11, 10
result = x - 1
console.log(result, x) // 10, 10
x
의 값은 변하지 않고 result
값만 계속 변화합니다. 만약 x
가 내부적으로 계산되는 임시 변수가 아니라 함수의 인자 등으로 처음 넘겨받은 값이라면 변하지 않는 것이 더욱 좋을 것입니다.
+
연산자는 피연산자 중 문자열이 하나라도 존재할 때 문자열로 형변환하여 연결합니다.
1 + "1" // 11
1 + "1" + 1 + 0 // 1110
// true는 1로, false는 0으로 변환
1 + true // 2
1 + false // 1
// null은 0으로 변환
1 + null // 1
// undefined는 정의되지 않았기 때문에
// 숫자로 변환되지 않음
1 + undefined // NaN
// 문자열에 + 붙이면 숫자타입으로 변환
1 + "1" // 2
할당 연산자는 우항 피연산자의 평가 결과를 좌항 변수에 할당합니다.
연산자 | 동작 | 부수효과 |
---|---|---|
= | 할당 | 우항의 표현식 결과 값을 좌항의 변수에 할당 |
+= | x = x + 2 | " |
-= | x = x - 2 | " |
*= | x = x * 2 | " |
/= | x = x / 2 | " |
%= | x = x % 2 | " |
let x = 3
x += 3 // 6
x -= 3 // 3
x *= 3 // 9
x /= 3 // 3
x %= 3 // 0
비교 연산자는 좌항과 우항의 피연산자를 비교해 그 값을 불리언(true/false) 타입으로 반환합니다.
값이 동등한 지를 평가하는 연산자입니다.
여기서 동등하다는 자바스크립트 엔진이 자체적으로 형변환을 한 후에 비교했을 때에 같다고 평가되었다는 의미입니다.
자바스크립트는 굉장히 자유로운 언어라고 했죠? 따라서 변수를 할당하면 자체적으로 타입을 추론합니다. 그리고 동등한지를 평가할 때 암묵적인 타입 변환을 합니다. 이런 형변환은 이따금 약간의 골칫거리가 되기도 하는데요. 형변환에 대해서는 추후 자세히 다룰 예정입니다. 지금은 자바스크립트가 타입을 추론해 바꾸기도 한다는 점만 알고 가기로 해요.
예시를 보겠습니다.
2 == 2 // true
// 암묵적 타입 변환해 타입이 같을 경우에
2 == "2" // true
분명 숫자와 문자열을 비교했는데 두 값이 같다고 true
를 반환하네요.
동등 비교가 타입을 바꿔서도 검사해주니 좋다고 생각할 수도 있지만, 사실 클린 코드를 작성하는 데에는 취약점입니다. 이미 우리는 앞서 타입 변환이 일어나 1 + '1'
이 11
이 되는 걸 확인했죠. 비슷한 예기치 못한 결과를 낳을 수 있기 때문에 일치 비교 연산자를 쓰는 것을 권장합니다.
일치 비교 연산자는 타입과 값이 모두 같을 경우에만 true를 반환합니다. 동등 비교보다 한층 강화된 연산자이기 때문에 엄격한 동등 연산자입니다.
2 === 2 // true
2 === "2" // false
일치 비교 연산자로 다 비교할 수 있으면 좋겠지만, 유의해야 할 값이 있습니다. 바로 NaN
입니다.
NaN === NaN // false
MDN의 설명을 참고하면, NaN
은 자신과 일치하지 않는 유일한 값입니다 (NaN is the only value that compares unequal to itself). 이건 일종의 버그에
따라서 isNaN()
동등, 일치가 있다면 동등하지 않은 것과 불일치하는 것도 비교할 수 있어야겠죠?
자바스크립트에서는 !
느낌표를 NOT 의미로 사용합니다.
1 != 5 // true
1 !== "1" // true
동등/일치 연산자에 !
를 붙여주면, 부동등 연산자는 값이 같지 않을 때, 불일치 연산자는 값과 타입이 모두 같지 않을 때 true
값을 리턴합니다.
수학 연산에서 쓰이는 기호와 같습니다.
1 >= 2 // false
2 > 1 // true
삼항 연산자는 자바스크립트에서 유일하게 3개의 피연산자를 가지는 연산자입니다.
삼항 연산자는 조건식의 평가에 따라 반환되는 값이 달라집니다.
삼항 연산자를 세 부분으로 나누어 살펴보겠습니다.
?
전까지는 조건식이 들어갑니다. 조건식의 결과는 Boolean 타입으로 평가되고, 만약 Boolean 타입이 아니라면 암묵적인 형변환을 통해 그 값을 Boolean으로 변환합니다.
만약 조건식이 true
라면 ?
뒤의 값이, false
라면 :
뒤의 값이 삼항연산자의 값으로 평가됩니다.
function isAdult(age) {
return age > 19 ? "You are an adult!" : "You are too young..."
}
isAdult(15) // 'You are too young...'
isAdult(24) // You are an adult!
삼항 연산자는 if...else
문과 비슷하다고 생각할 수 있는데요. 유의해야 할 차이점이 있습니다. if...else
는 조건문이고, 삼항 연산자는 표현식이란 점입니다.
이전 글에서 값, 식, 문의 차이를 알아보며 문은 변수에 할당할 수 없지만, 표현식은 값으로 평가되어 할당할 수 있다고 설명한 바가 있습니다. 따라서 값처럼 사용할 수 있는 삼항 연산자는 무척 유용합니다.
논리 연산자는 우항과 좌항의 피연산자를 논리적으로 연산합니다.
논리적으로 연산한다는 말이 조금 어렵게 느껴집니다. 간단하게 Boolean 연산이라고 생각하면 됩니다. 논리연산은 true
와 false
만 존재하는 연산입니다.
연산자 | 동작 | 의미 |
---|---|---|
|| | 논리합(OR) | 피연산자 중 하나라도 true이면 true |
&& | 논리곱(AND) | 피연산자 모두 true여야 true |
! | 논리부정(NOT) | 피연산자의 값을 반전한 값 반환 |
이렇게만 봐서는 좀 어렵습니다. 예제를 함께 살펴보겠습니다.
// 논리합 (||)
true || true // true
true || false // true
false || true // true
false || false // false
// 논리곱(&&)
true && true // true
true && false // false
false && true // false
false && false // false
// 부정 (!)
!true // false
!false // true
논리 부정 연산자(!)는 항상 Boolean값으로 반환되는데, 피연산자의 값이 Boolean이 아니면 Boolean 값으로 암묵적 형변환하여 평가합니다.
console.log(!0) // true
console.log(!"Any String") // false
논리 곱 연산자(&&)는 늘 2개의 피연산자 중 하나로 평가됩니다.
console.log("Apple" && "Banana") // Banana
typeof 연산자는 이름에서 알 수 있듯 피연산자의 타입을 문자열로 반환합니다.
typeof 연산자가 반환하는 값의 종류는 다음과 같습니다.
사실 typeof 로 검사해도 우리가 원하는 타입과 정확히 맞아떨어지는 결과가 반환되지만은 않습니다.
typeof "" // string (null 예상)
typeof NaN // number
typeof null // object
typeof [] // object
typeof new Date() // object
조금 이상하죠? 특히 null
을 검사했는데 object로 넘기는 건 정말 이상합니다. 이건 자바스크립트의 버그입니다. 하지만 기존에 이미 작성된 코드와의 호환을 위해 의도적으로 남긴 버그입니다.
따라서 null을 체크할 때에는 ===
일치 연산자를 사용하는 것이 좋습니다.
ES6 이후 자바스크립트 스펙에서 추가된 연산자들은 추후 알아보도록 하겠습니다.
다음 글에서는 제어문에 대해 알아보겠습니다.
◾ 값, 식, 문 👈 이전 글 보기
◾ 제어문(1) - 조건문 👈 다음 글 보기