index
1. 연산자(operator)는 무엇인가?
연산자는 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리, 타입, 지수연산 등을 수행해 하나의 값을 만든다.
피연산자가 값으로 평가될 수 있는 표현식
연산자는 피연산자를 연산하여 새로운 값으로 만드는 동사
1.1 산술 연산자(arithmetic operator)
산술 연산자는 피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값을 만든다.
1.1.1 이항 산술 연산자 (binary)
이항 산술 연산자는 두 개의 피연산자를 다룹니다. 연산자가 두 개의 값을 취하고, 이 두 값 사이에서 연산을 수행하기 때문에 “이항(binary)”이라고 부릅니다. “이”는 두 개를 의미하며, “항”은 연산에 사용되는 피연산자를 의미합니다.
1.1.2 단항 산술 연산자 (Unary)
단항 산술 연산자는 단 하나의 피연산자만을 다룹니다. “단(unary)”은 하나를 의미하며, 따라서 단항 연산자는 하나의 피연산자에 대해 연산을 수행합니다.
⭐️ 증가/감소(++/–) 연산자는 피연산자의 값을 변경하는 부수효과가 있다!
전위 증가 / 감소 연산자(Prefix increment, decrement operator)는 먼저 피연산자의 값을 증가 · 감소 시킨 후, 다른 연산 수행
후위 증가 / 감소 연산자(Prefix increment, decrement operator)는 먼저 다른 연산을 수행한 후, 피연산자의 값을 증가 · 감소시킨다.
let x = 5,
result;
// 선할당 후증가postfix increment operator)
result = x++;
console.log(result, x); // 5 6, 일단 result에 할당! + x값 증가
// 선증가 후할당(prefix increment operator)
result = ++x;
console.log(result, x); // 7 7, 일단 x값 증가 + result에 재할당
// 선할당 후감소(postfix decrement operator)
result = x--;
console.log(result, x); // 7 6, 일단 result에 할당! + x값 감소
// 선감소 후할당(prefix decrement operator)
result = --x;
console.log(result, x); // 5 5, 일단 x값 감소 + result에 재할당
1.1.3 문자열 연결 연산자
// 문자열 연결 연산자
"1" + 2; // → '12'
// 산술 연산자
1 + 2; // → 3
// true는 1로 타입 변환한다.
1 + true; // → 2
// false는 0으로 타입 변환한다.
1 + false; // → 1
// null은 0으로 타입 변환한다.
1 +
null + // → 1
// undefined는 숫자로 타입 변환되지 않는다.
undefined; // → NaN
1 + undefined; // → NaN
1+ true를 연산하면 자바스크립트 엔진은 암묵적으로 불리언 타입의 값인 true를 숫자 타입인 1로 강제로 변환한 후 연산하는데 이를 암묵적 타입변환(Implicit coercion)또는 타입 강제변환(type coercion)이라고 한다.
1.2 부수효과(Side Effect)
1.2.1 여기서 부수효과(side effect)란 무엇일까?
자바스크립트에서 “부수효과”란 특정 코드(주로 함수나 연산자)를 실행할 때, 그 코드가 명시적으로 반환하는 값 이외에 추가적으로 발생하는 상태 변화나 외부 영향력을 의미합니다. 이런 부수효과는 코드의 다른 부분에 영향을 줄 수 있습니다.
**📌 <부수효과의 예시="">**부수효과의>
부수효과는 다음과 같은 상황에서 발생할 수 있습니다:
① 변수 값의 변경
-
예를 들어, 변수
x
의 값을 증가시키는 연산자++
는 그 자체로 부수효과를 일으킵니다. -
let x = 5; x++; // x의 값이 6으로 변경됨
- 여기서
x++
는x
의 값을 1 증가시키며, 이 자체가x
의 상태를 변경하는 부수효과입니다.
② 전역 변수나 외부 변수의 변경
-
함수 내부에서 전역 변수를 변경하는 것도 부수효과입니다.
-
let globalVar = 10; function changeGlobal() { globalVar = 20; } changeGlobal(); // globalVar의 값이 20으로 변경됨
changeGlobal
함수는globalVar
의 값을 변경하는 부수효과를 발생시킵니다.
③ 외부 상태의 변경
-
객체나 배열 같은 데이터 구조를 함수에서 변경할 때도 부수효과가 발생합니다.
-
let obj = { value: 10 }; function modifyObj(o) { o.value = 20; } modifyObj(obj); // obj.value가 20으로 변경됨
- 이 함수는
obj
객체의value
속성을 변경하는 부수효과를 일으킵니다.
1.2.2 부수효과의 중요성
부수효과는 때로는 코드에서 필요한 경우도 있지만, 예측하지 못한 방식으로 작동하여 버그를 일으킬 수 있습니다. 예를 들어, 함수가 호출될 때마다 외부 상태를 변경하면, 이 함수가 여러 곳에서 호출되었을 때 예기치 않은 결과를 초래할 수 있습니다. 이 때문에 함수형 프로그래밍에서는 부수효과가 없는 순수 함수를 권장합니다. 순수 함수는 입력값만을 가지고 결과를 반환하며, 외부 상태를 변경하지 않기 때문에 부수효과가 없습니다.
1.2.3 정리
- 부수효과: 코드 실행 중에 반환 값 이외에 추가적으로 발생하는 상태 변화나 외부 영향.
- 부수효과의 예시: 변수 값의 변경, 전역 변수의 수정, 객체나 배열 등의 외부 데이터 구조 변경.
- 함수형 프로그래밍: 부수효과를 최소화하여 코드의 예측 가능성을 높이고, 디버깅을 쉽게 하려는 프로그래밍 패러다임.
1.3 할당 연산자(assignment operator)
할당 연산자 | 예 | 동일 표현 | 부수 효과 |
---|---|---|---|
= | x = 5 | x = 5 | O |
+= | x += 5 | x = x + 5 | O |
-= | x -= 5 | x = x - 5 | O |
*= | x *= 5 | x = x * 5 | O |
/= | x /= 5 | x = x / 5 | O |
%= | x %= 5 | x = x % 5 | O |
1.4 비교 연산자(comparison operator)
비교 연산자 | 의미 | 사례 | 설명 | 부수 효과 |
---|---|---|---|---|
== | 동등 비교 | x == y | x와 y의 값이 같음 | X |
=== | 일치 비교 | x === y | x와 y의 값과 타입이이 같음 | X |
!= | 부동등 비교 | x != y | x와 y의 값이 다름 | X |
!== | 불일치 비교 | x !== y | x와 y의 값과 타입이이 다름 | X |
> | x > y | x가 y보다 크다 | X | |
< | x < y | x가 y보다 작다 | X | |
>= | x >= y | x가 y보다 크거나 같다 | X | |
<= | x <= y | x가 y보다 작거나 같다 | X |
1.5 삼항 조건 연산자(ternary operator)
let x = 10;
// 삼항 조건 연산자 표현식은 표현식인 문이다. 따라서 값처럼 사용할 수 있다.
let result = x % 2 ? 'odd num', 'even num';
console.log(result); // 짝수;
let x = 10;
// if...else 문은 표현식이 아닌 문이다. 따라서 값처럼 사용할 수 없다.
let result = if (x%2) {result = '홀수';} else {result = '짝수'; };
// SyntaxErro: unexpected token if
🧐 if…else 문은 왜 값처럼 사용할 수 없을까?
if … else 문은 보다 복잡한 제어 흐름을 제공하기 위해 문으로 설계된 것입니다.
삼항 조건 연산자는 간단하게 값을 반환하는 구조를 표현하기 위해 표현식으로 설계되었기 때문
1.6 논리 연산자(logical operator)
논리 연산자 | 의미 | 부수 효과 |
---|---|---|
|| | 논리합(OR) | X |
&& | 논리곱(AND) | X |
! | 부정(NOT) | X |
1.7 쉼표 연산자(comma operator)
쉽표(,) 연산자는 왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환한다.
let x, y, z;
(x = 1), (y = 2), (z = 3); // 3
1.8 그룹 연산자(group operator)
소괄호(‘( )’)로 피연산자를 감싸는 그룹연산자는 자신의 피연산자인 표현식을 가장 먼저 평가한다. 따라서 그룹 연산자를 사용하면 연산자의 우선순위를 조절할 수 있다. 그룹 연산자는 연산자 우선순위가 가장 높다.
10 * 2 + 3; // → 23
// 그룹 연산자를 사용하여 우선순위를 조절
10 * (2 + 3); // → 50
1.9 typeof 연산자(typeof operator)
typeof ""; // — "string"
typeof 1; // — "number"
typeof NaN; // — "number"
typeof true; // — "boolean"
typeof undefined; // — "undefined"
typeof Symbol(); // — "symbol"
typeof null; // — "object" (자바스크립트 버그)
typeof []; // — "object"
typeof {}; // — "object"
typeof new Date(); // — "object"
typeof /test/gi; // — "object"
typeof function () {}; // — "function"
// // null 타입인지 확인을 위해서는 일치 연산자(===)를 사용하자
let foo = null;
typeof foo === null; // false
foo === null; // true
1.10 지수 연산자(exponent operator)
좌항의 피연산자를 밑(base)으로, 우항의 피연산자를 지수(exponent)로 거듭 제곱하여 숫자값을 반환한다.
2 ** 2; // → 4
2 ** 2.5; // → 5.65685424949238
2 ** 0; // → 1
2 ** -2; // → 0.5
1.11 연산자 결합 순서
연산자의 결합 순서(Associativity)는 동일한 우선순위를 가진 연산자들이 한 식(expression)에서 여러 번 등장할 때, 그 연산자들이 어떤 순서로 계산되는지를 결정하는 규칙입니다. 이는 연산자들이 어떻게 결합되며, 어떤 순서로 평가되는지를 이해하는 데 매우 중요합니다.
1. 좌결합(Left-Associativity)
좌결합성(Left-Associativity)을 가진 연산자는 왼쪽에서 오른쪽으로 평가됩니다. 즉, 동일한 우선순위를 가진 연산자들이 연속해서 나타날 때, 왼쪽부터 차례대로 계산됩니다.
주로 산술 연산자, 대부분의 비트 연산자 등이 좌결합성을 가집니다.
let result = 10 - 5 - 2;
/* <계산 과정>
10 - 5가 먼저 계산됩니다. 결과는 5입니다.
그런 다음 5 - 2가 계산됩니다. 결과는 3입니다.
*/
2. 우결합(Left-Associativity)
우결합성(Right-Associativity)을 가진 연산자는 오른쪽에서 왼쪽으로 평가됩니다. 즉, 동일한 우선순위를 가진 연산자들이 연속해서 나타날 때, 오른쪽부터 차례대로 계산됩니다.
주로 할당 연산자, 지수 연산자 등이 우결합성을 가집니다.
let result = 2 ** (3 ** 2); // 결과는 512
/* <계산 과정>
3 ** 2가 먼저 계산됩니다. 결과는 9입니다.
그런 다음 2 ** 9가 계산됩니다. 결과는 512입니다.
*/