[ javascript ] 공식문서 읽고 열흘 벼락치기: Expressions and Operators

김쟇연·2025년 9월 5일
post-thumbnail

📝 Day 04 – 표현식과 연산자 (Expressions and Operators)

공식 문서 해당 챕터 바로가기 ! 🐱

들어가며

자바스크립트에서 표현식이란 건 값 하나 쥐어짜내는 제일 작은 단위다. 연산자는 그 값들 억지로 붙여서 결과를 갈겨낸다. 어떤 건 값만 던지고 끝나지만, 어떤 건 부수효과까지 싸질러서 코드판을 싹 다 개판으로 만들어버린다.

이번 장에서는 자주 쓰이는 연산자와 표현식이 어떻게 굴러가는지, 누가 먼저 치고 나가고 어떻게 붙어 쳐먹는지까지 싸그리 까발려 보겠다.


표현식의 두 얼굴

  • 부수효과 있음: x = 7x에 7을 대입하고, 전체 표현식의 값도 7.
  • 평가 전용: 3 + 4 → 7을 만들지만, 어딘가에 대입하지 않으면 즉시 버려진다.

연산자는 =, +처럼 표현식을 연결한다. 이때 우선순위결합성을 이해하면 평가 순서를 예측할 수 있다.

const x = 1 + 2 * 3; // 7, *가 +보다 먼저
const y = (1 + 2) * 3; // 9, 괄호로 우선순위 재정의
  • 결합성(associativity): 대입(=)은 오른쪽 결합이다. y = x = f()y = (x = f())와 같다.

연산자 형태

  • 이항: a + b, x * y (모두 중위 표기)
  • 단항: ++x(접두), x++(접미). 접미는 ++, -만 가능.
  • 삼항: 조건 연산자 cond ? a : b

대입(Assignment)

가장 기본은 =이며, 축약형이 다수 존재한다.

이름축약의미
단순 대입x = f()x = f()
더하기 대입x += f()x = x + f()
빼기/곱/나누기/나머지-=, *=, /=, %=각각
제곱**=x = x ** f()
비트 시프트/비트 연산<<=, >>=, >>>=, &=, ^=, `=`
논리 대입&&=, `

프로퍼티 대입

const obj = {};
obj.x = 3;           // { x: 3 }
const k = "y";
obj[k] = 5;          // { x: 3, y: 5 }

원시값에는 프로퍼티를 쓸 수 없다(엄격 모드에서는 에러).

구조 분해 대입(Destructuring)

const [a, b] = [10, 20];
const {name, age: years} = { name: "Ari", age: 30 };

평가·중첩

대입식 자체가 을 반환한다.

let x;
const y = (x = f());   // x와 y 모두 f()의 결과
console.log(x = f());  // 대입 결과를 바로 로그

스타일 주의: 대입 체인 지양

const z = y = x = f();
// 실제로는 z만 선언되고, x/y는 전역 유출(슬로피 모드) 또는 에러(스트릭트)

비교(Comparison)

  • 느슨한 동등 == / 부등 != : 필요 시 타입 변환 수행
  • 엄격 동등 === / 부등 !== : 타입까지 같아야 참
  • 크기 비교 >, >=, <, <= : 숫자 비교(문자열은 유니코드 사전순)
3 == "3";    // true
3 === "3";   // false
"12" > 2;    // true (숫자 변환 후 비교되는 경우가 많음)

메모: =>는 비교 연산자가 아니라 화살표 함수 표기다.


산술(Arithmetic)

표준 연산 + - * / 외에 다음이 있다.

12 % 5;   // 2 (나머지)
++x; x++; // 증가 (접두/접미)
--x; x--; // 감소
-x;       // 부호 반전
+"3";     // 3 (단항 +는 수 변환)
2 ** 3;   // 8 (지수)

0으로 나누면 Infinity(부동소수점 규칙).


비트(Bitwise) & 시프트(Shift)

32비트 정수로 변환해 비트 단위로 연산한다.

  • 논리: &(AND), |(OR), ^(XOR), ~(NOT)
  • 시프트: <<, >>(부호 유지), >>>(제로 필)
15 & 9;  // 9  (1111 & 1001 = 1001)
15 ^ 9;  // 6  (0110)
~15;     // -16  // ~x === -x - 1
9 << 2;  // 36
-9 >> 2; // -3  (부호 전파)

논리(Logical) & 단축 평가

&&, ||, ??, !

  • 값 선택자: 불리언뿐 아니라 피연산자 중 하나를 반환한다.
  • 단축 평가:
    • falsy && anything → falsy
    • truthy || anything → truthy
    • non-nullish ?? anything → 앞의 값
"Cat" && "Dog"; // "Dog"
false || "Cat"; // "Cat"
null ?? "N/A";  // "N/A"
0 ?? 42;        // 0  (||와의 중요한 차이점)
!true;          // false

BigInt 연산

대부분의 수 연산/비트 연산을 지원한다(단, >>> 없음).

1n + 2n;        // 3n
1n / 2n;        // 0n (0으로 내림)
40000000000000000n >> 2n; // OK
// 혼용 금지
// 1n + 2;      // TypeError
Number(1n) + 2;  // 3 (명시 변환)

문자열 연산

  • 연결: +, +=
"my " + "string"; // "my string"
let s = "alpha";
s += "bet";       // "alphabet"

조건(삼항) 연산자

const status = age >= 18 ? "adult" : "minor";

간단 분기에는 if…else보다 읽기 좋다.


콤마(,) 연산자

두 피연산자를 평가하고 마지막 값을 반환. 주로 for의 헤더에서 다중 업데이트에 사용. 일반 코드에서는 가독성 때문에 지양.

for (let i = 0, j = 9; i <= j; i++, j--) {
  console.log(i, j);
}

단항(기타)

delete

객체의 프로퍼티를 제거한다. 성공 시 true.

const o = { h: 4 };
delete o.h;     // true
delete Math.PI; // false (비구성 프로퍼티)

배열 요소를 delete하면 구멍(hole)만 남고 길이는 그대로다. splice 등 배열 메서드를 사용하자.

typeof

피연산자의 타입을 문자열로 반환.

typeof (() => 7); // "function"
typeof 62;        // "number"
typeof null;      // "object"  // 역사적 이유
typeof foo;       // "undefined" (선언 전 식별자)

void

표현식을 평가만 하고 값을 버림.


관계(Relational)

in

프로퍼티 존재 여부(키 기준). 배열에는 인덱스로 검사.

"PI" in Math;                 // true
const trees = ["redwood","bay"];
0 in trees;                   // true
"bay" in trees;               // false (값이 아니라 키 검사)

instanceof

생성자 기반 타입 체크.

const m = new Map();
m instanceof Map; // true

기본 표현식(Basic Expressions)

this

메서드 호출 시 수신 객체를 가리키는 암묵 인자.

function getFullName() { return `${this.first} ${this.last}`; }
const p = { first: "Chris", last: "Martin", getFullName };
p.getFullName(); // "Chris Martin"

그룹 연산자 ()

우선순위 제어.

(1 + 2) * 3; // 9

프로퍼티 접근자

점 표기/대괄호 표기.

obj.prop; obj["prop"];

옵셔널 체이닝 ?.

null/undefined이면 짧게 끊고 undefined 반환.

user.profile?.name;
maybeFn?.();

new

생성자 호출로 인스턴스 생성.

const d = new Date();

super

상위(부모) 생성자/메서드 호출(클래스 문맥).

super(args);
super.method();

마무리

  • 표현식은 을 만들고, 연산자는 그 값을 결합한다.
  • 우선순위/결합성을 모르면 버그가 늘어난다 → 괄호로 명시하라.
  • == 대신 ===, 기본값에는 ??, 배열 순회에는 delete 지양.
  • 대입 체인은 선언과 섞지 말고, 부수효과가 있는 표현식은 가독성을 우선하라.

요약하면, 연산자는 값 선택과 제어의 언어다. 규칙(우선순위·결합성)과 각 연산자의 미묘한 차이만 챙겨두면, 의도가 선명한 표현식을 만들 수 있다.

profile
그래도 해야지 어떡해

0개의 댓글