Backend
home
🟨

JavaScript 기본 문법 완전 정복

생성일
2026/06/03 09:13
태그
JavaScript
JavaScript는 1995년 Brendan Eich가 단 10일 만에 설계한 언어다. 처음엔 웹 브라우저에서 간단한 동작을 처리하는 스크립트 언어로 시작했지만, 지금은 프론트엔드·백엔드(Node.js)·모바일(React Native)까지 아우르는 범용 언어가 됐다.
이 글은 JavaScript를 다시 처음부터 훑으면서 기본기를 단단하게 다지는 데 목적이 있다.

1. 변수 선언 — var / let / const

JavaScript에는 변수를 선언하는 방법이 세 가지 있다. 셋의 차이를 모르면 예상치 못한 버그가 생긴다.
// var: 함수 스코프, 호이스팅 O, 재선언 O → 사용 지양 var x = 1; var x = 2; // 재선언 허용 (버그 유발) console.log(x); // 2 // let: 블록 스코프, 재선언 X, 재할당 O let count = 0; count = 10; // 재할당 가능 // let count = 20; // SyntaxError: 재선언 불가 // const: 블록 스코프, 재선언 X, 재할당 X const MAX = 100; // MAX = 200; // TypeError // 단, const 객체/배열의 내부는 변경 가능 const user = { name: '홍길동' }; user.name = '김철수'; // 허용 (참조 자체는 변경 안 함) user.age = 30; // 속성 추가도 허용
JavaScript
복사
구분
스코프
재선언
재할당
호이스팅
var
함수
(undefined로)
let
블록
(TDZ, 접근 불가)
const
블록
(TDZ, 접근 불가)
TDZ (Temporal Dead Zone): let/const는 선언 전에 접근하면 ReferenceError가 발생한다. 호이스팅은 되지만 초기화 전 구간에서 접근 자체가 막혀 있다.

2. 데이터 타입

2-1. 원시 타입 (Primitive)

// Number: 정수와 부동소수점을 하나의 타입으로 const n = 42; const pi = 3.14; const inf = Infinity; const nan = NaN; // Not a Number (계산 실패 시) console.log(0.1 + 0.2); // 0.30000000000000004 (부동소수점 주의) // BigInt: 2^53 - 1보다 큰 정수 const big = 9007199254740991n; const big2 = BigInt('12345678901234567890'); // String const str1 = '작은따옴표'; const str2 = "큰따옴표"; const str3 = `템플릿 리터럴: ${n + 1}`; // 표현식 삽입 가능 // Boolean const isTrue = true; const isFalse = false; // null: 명시적으로 '값 없음' const empty = null; // undefined: 값이 할당되지 않은 상태 let notAssigned; // undefined // Symbol: 유일한 식별자 const id1 = Symbol('id'); const id2 = Symbol('id'); console.log(id1 === id2); // false (항상 고유)
JavaScript
복사

2-2. 타입 확인

console.log(typeof 42); // 'number' console.log(typeof 'hello'); // 'string' console.log(typeof true); // 'boolean' console.log(typeof undefined); // 'undefined' console.log(typeof null); // 'object' ← JS의 유명한 버그 console.log(typeof {}); // 'object' console.log(typeof []); // 'object' console.log(typeof function(){}); // 'function' // 배열 판별에는 Array.isArray 사용 console.log(Array.isArray([])); // true console.log(Array.isArray({})); // false // null 판별 console.log(empty === null); // true
JavaScript
복사

2-3. 암묵적 형 변환

// 느슨한 비교 (==): 형 변환 후 비교 console.log(0 == false); // true console.log('' == false); // true console.log(null == undefined); // true console.log(1 == '1'); // true // 엄격한 비교 (===): 형 변환 없이 타입까지 비교 → 항상 이걸 써야 함 console.log(0 === false); // false console.log(1 === '1'); // false // falsy 값: false로 취급되는 값 // false, 0, -0, 0n, '', null, undefined, NaN console.log(Boolean(0)); // false console.log(Boolean('')); // false console.log(Boolean(null)); // false console.log(Boolean([])); // true ← 빈 배열은 truthy console.log(Boolean({})); // true ← 빈 객체도 truthy
JavaScript
복사

3. 연산자

// 산술 console.log(10 % 3); // 1 (나머지) console.log(2 ** 10); // 1024 (거듭제곱, ES2016) // 논리 console.log(true && false); // false console.log(true || false); // true console.log(!true); // false // 단락 평가 (Short-circuit evaluation) const name = null; console.log(name || '기본값'); // '기본값' (||: 왼쪽 false면 오른쪽) console.log(name && name.length); // null (&&: 왼쪽 false면 왼쪽 반환) // Nullish Coalescing (??, ES2020): null/undefined일 때만 오른쪽 console.log(null ?? '기본값'); // '기본값' console.log(0 ?? '기본값'); // 0 (0은 null/undefined가 아님) console.log('' ?? '기본값'); // '' (빈 문자열도 그대로) // Optional Chaining (?., ES2020): null/undefined면 undefined 반환 const obj = { a: { b: { c: 42 } } }; console.log(obj?.a?.b?.c); // 42 console.log(obj?.x?.y?.z); // undefined (에러 없음) // 스프레드 / 나머지 const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5] function sum(...nums) { // 나머지 매개변수 return nums.reduce((a, b) => a + b, 0); } console.log(sum(1, 2, 3, 4)); // 10
JavaScript
복사

4. 제어문

// if-else const score = 85; if (score >= 90) { console.log('A'); } else if (score >= 80) { console.log('B'); // 출력 } else { console.log('F'); } // 삼항 연산자 const grade = score >= 60 ? '합격' : '불합격'; // switch const day = 'MON'; switch (day) { case 'SAT': case 'SUN': console.log('주말'); break; default: console.log('평일'); // 출력 } // for for (let i = 0; i < 5; i++) { process.stdout.write(i + ' '); // 0 1 2 3 4 } // for...of: 이터러블 순회 (배열, 문자열, Map, Set) const fruits = ['사과', '바나나', '딸기']; for (const fruit of fruits) { console.log(fruit); } // for...in: 객체 키 순회 (프로토타입 체인까지 탐색하므로 주의) const person = { name: '홍길동', age: 30 }; for (const key in person) { if (Object.hasOwn(person, key)) { // 자신의 속성만 console.log(`${key}: ${person[key]}`); } } // while / do-while let i = 0; while (i < 3) { console.log(i++); }
JavaScript
복사

5. 함수

5-1. 선언 방식 비교

// 함수 선언식: 호이스팅 O (선언 전에 호출 가능) function greet(name) { return `안녕하세요, ${name}!`; } // 함수 표현식: 호이스팅 X const greet2 = function(name) { return `Hi, ${name}!`; }; // 화살표 함수 (Arrow Function, ES2015) // - this를 바인딩하지 않음 (렉시컬 this) // - 생성자로 사용 불가 // - arguments 객체 없음 const greet3 = (name) => `Hello, ${name}!`; const double = n => n * 2; // 매개변수 하나면 괄호 생략 const getObj = () => ({ key: 1 }); // 객체 반환 시 괄호 필요 console.log(greet('길동')); // 안녕하세요, 길동! console.log(double(5)); // 10
JavaScript
복사

5-2. 매개변수

// 기본값 매개변수 (ES2015) function createUser(name, role = 'user', active = true) { return { name, role, active }; } console.log(createUser('홍길동')); // { name: '홍길동', role: 'user', active: true } console.log(createUser('관리자', 'admin')); // { name: '관리자', role: 'admin', active: true } // 나머지 매개변수 function logAll(first, ...rest) { console.log('첫 번째:', first); console.log('나머지:', rest); } logAll(1, 2, 3, 4); // 첫 번째: 1 / 나머지: [2, 3, 4]
JavaScript
복사

5-3. 클로저 (Closure)

함수가 생성될 때의 외부 변수를 기억하는 메커니즘이다.
function makeCounter(start = 0) { let count = start; // 클로저가 기억하는 변수 return { increment: () => ++count, decrement: () => --count, getCount: () => count, }; } const counter = makeCounter(10); console.log(counter.increment()); // 11 console.log(counter.increment()); // 12 console.log(counter.decrement()); // 11 console.log(counter.getCount()); // 11 // count 변수는 외부에서 직접 접근 불가 → 캡슐화 // 실용 예: 메모이제이션 function memoize(fn) { const cache = new Map(); return function(...args) { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); const result = fn.apply(this, args); cache.set(key, result); return result; }; } const expensiveFn = memoize((n) => { console.log('계산 중...'); return n * n; }); console.log(expensiveFn(10)); // 계산 중... → 100 console.log(expensiveFn(10)); // (캐시) → 100
JavaScript
복사

6. 객체 (Object)

6-1. 기본 조작

const user = { name: '홍길동', age: 30, 'my-key': '특수문자 키', // 문자열 키 greet() { // 메서드 단축 문법 return `안녕, 나는 ${this.name}`; }, }; // 접근 console.log(user.name); // 점 표기법 console.log(user['my-key']); // 대괄호 표기법 (동적 키 접근) // 추가 / 수정 / 삭제 user.email = 'test@test.com'; user.age = 31; delete user['my-key']; // 존재 확인 console.log('name' in user); // true console.log(user.hasOwnProperty('email')); // true // 키 / 값 / 엔트리 console.log(Object.keys(user)); // ['name', 'age', 'email', 'greet'] console.log(Object.values(user)); // ['홍길동', 31, 'test@test.com', f] console.log(Object.entries(user)); // [['name','홍길동'], ...]
JavaScript
복사

6-2. 구조 분해 할당 (Destructuring)

// 객체 구조 분해 const { name, age, city = '서울' } = user; // 기본값 지정 가능 console.log(name, age, city); // 홍길동 31 서울 // 이름 변경 const { name: userName } = user; console.log(userName); // 홍길동 // 중첩 객체 const { address: { street } = {} } = { address: { street: '강남대로' } }; console.log(street); // 강남대로 // 배열 구조 분해 const [first, second, ...rest] = [10, 20, 30, 40, 50]; console.log(first, second, rest); // 10 20 [30, 40, 50] // 함수 매개변수에서 바로 분해 function display({ name, age }) { console.log(`${name} (${age}세)`); } display(user); // 홍길동 (31세)
JavaScript
복사

6-3. 객체 복사와 병합

// 얕은 복사 const copy1 = { ...user }; // 스프레드 const copy2 = Object.assign({}, user); // Object.assign // 병합 (뒤 객체가 우선) const merged = { ...user, age: 99, role: 'admin' }; // 깊은 복사 (중첩 객체까지) const deep = JSON.parse(JSON.stringify(user)); // 함수, undefined, Symbol 제외 const deep2 = structuredClone(user); // ES2022: 더 안전한 방법
JavaScript
복사

7. 배열 (Array)

7-1. 기본 조작

const arr = [1, 2, 3, 4, 5]; // 추가 / 제거 arr.push(6); // 뒤에 추가 → [1,2,3,4,5,6] arr.pop(); // 뒤에서 제거 → 6 반환 arr.unshift(0); // 앞에 추가 → [0,1,2,3,4,5] arr.shift(); // 앞에서 제거 → 0 반환 // splice: 임의 위치 삽입/삭제 arr.splice(2, 1, 99); // 인덱스 2에서 1개 삭제 후 99 삽입 console.log(arr); // [1, 2, 99, 4, 5] // slice: 잘라내기 (원본 불변) const sliced = arr.slice(1, 3); // [2, 99] // 검색 console.log(arr.indexOf(99)); // 2 console.log(arr.includes(99)); // true console.log(arr.find(n => n > 3)); // 4 console.log(arr.findIndex(n => n > 3)); // 3
JavaScript
복사

7-2. 고차 함수 (Higher-Order Function)

const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // map: 각 요소를 변환한 새 배열 반환 const doubled = nums.map(n => n * 2); console.log(doubled); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] // filter: 조건을 만족하는 요소만 추출 const evens = nums.filter(n => n % 2 === 0); console.log(evens); // [2, 4, 6, 8, 10] // reduce: 누산기로 단일 값 생성 const sum = nums.reduce((acc, cur) => acc + cur, 0); console.log(sum); // 55 // 체이닝 const result = nums .filter(n => n % 2 === 0) // [2, 4, 6, 8, 10] .map(n => n ** 2) // [4, 16, 36, 64, 100] .reduce((a, b) => a + b, 0); // 220 console.log(result); // 220 // forEach: 반환값 없음, 부수효과 목적 nums.forEach((n, idx) => { if (idx < 3) console.log(`[${idx}] ${n}`); }); // some: 하나라도 조건 만족하면 true console.log(nums.some(n => n > 9)); // true // every: 모두 조건 만족하면 true console.log(nums.every(n => n > 0)); // true // flat / flatMap const nested = [[1, 2], [3, 4], [5]]; console.log(nested.flat()); // [1, 2, 3, 4, 5] const sentences = ['hello world', 'foo bar']; console.log(sentences.flatMap(s => s.split(' '))); // ['hello', 'world', 'foo', 'bar'] // 정렬 (주의: 기본 정렬은 문자열 기준) const nums2 = [10, 1, 21, 2]; console.log(nums2.sort()); // [1, 10, 2, 21] ← 문자열 정렬 console.log(nums2.sort((a, b) => a - b)); // [1, 2, 10, 21] ← 숫자 정렬
JavaScript
복사

8. this 바인딩

JavaScript에서 this호출 방식에 따라 값이 달라진다.
// 1. 일반 함수: 전역 객체 (브라우저: window, Node.js: global) function showThis() { console.log(this); } showThis(); // window (strict mode에서는 undefined) // 2. 메서드: 호출한 객체 const obj = { name: '객체', show() { console.log(this.name); }, }; obj.show(); // '객체' // 문제 상황: 메서드를 변수에 담으면 this가 사라짐 const fn = obj.show; fn(); // undefined (window.name) // 3. 화살표 함수: 렉시컬 this (선언된 위치의 this) const obj2 = { name: '객체2', greet: () => console.log(this.name), // 화살표: this = 상위 스코프 (window) greetOk() { const inner = () => console.log(this.name); // 여기서는 obj2 inner(); }, }; obj2.greet(); // undefined obj2.greetOk(); // '객체2' // 4. call / apply / bind: this 명시적 지정 function introduce(greeting, ending) { return `${greeting}, 나는 ${this.name}${ending}`; } const me = { name: '길동' }; console.log(introduce.call(me, '안녕', '!')); // 안녕, 나는 길동! console.log(introduce.apply(me, ['Hi', '~'])); // Hi, 나는 길동~ const boundFn = introduce.bind(me, '헬로'); // this + 첫 인자 고정 console.log(boundFn('?')); // 헬로, 나는 길동?
JavaScript
복사

9. 프로토타입과 클래스

9-1. 프로토타입 체인

// JS의 모든 객체는 프로토타입 체인을 통해 상위 객체의 속성을 상속 const arr = [1, 2, 3]; // arr → Array.prototype → Object.prototype → null console.log(arr.hasOwnProperty('length')); // true (자신의 속성) console.log(arr.hasOwnProperty('map')); // false (Array.prototype에 있음)
JavaScript
복사

9-2. 클래스 (ES2015+)

class Animal { #name; // private 필드 (ES2022) constructor(name, sound) { this.#name = name; this.sound = sound; } speak() { return `${this.#name}이(가) ${this.sound} 소리를 냅니다.`; } get name() { return this.#name; } // getter static create(name, sound) { // 정적 메서드 return new Animal(name, sound); } } class Dog extends Animal { #breed; constructor(name, breed) { super(name, '멍멍'); // 부모 생성자 호출 this.#breed = breed; } speak() { return super.speak() + ` (품종: ${this.#breed})`; } fetch() { return `${this.name}이(가) 공을 가져옵니다.`; } } const dog = new Dog('바둑이', '진돗개'); console.log(dog.speak()); // 바둑이이(가) 멍멍 소리를 냅니다. (품종: 진돗개) console.log(dog.fetch()); // 바둑이이(가) 공을 가져옵니다. console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true
JavaScript
복사

10. 비동기 처리

10-1. 콜백 (Callback)

// 비동기 작업의 가장 원초적인 형태 setTimeout(() => { console.log('1초 후 실행'); }, 1000); // 콜백 지옥: 중첩이 깊어지면 가독성이 급격히 나빠짐 getUser(1, (user) => { getOrders(user.id, (orders) => { getProduct(orders[0].productId, (product) => { console.log(product.name); // 콜백 지옥 }); }); });
JavaScript
복사

10-2. Promise

// Promise: 비동기 작업의 최종 완료 또는 실패를 나타내는 객체 function fetchData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url) { resolve({ data: '응답 데이터' }); // 성공 } else { reject(new Error('URL이 없음')); // 실패 } }, 1000); }); } // then / catch / finally 체이닝 fetchData('https://api.example.com') .then(res => { console.log(res.data); return '가공된 데이터'; }) .then(processed => console.log(processed)) .catch(err => console.error(err.message)) .finally(() => console.log('완료')); // Promise 유틸리티 const p1 = Promise.resolve(1); const p2 = Promise.resolve(2); const p3 = Promise.reject(new Error('실패')); // all: 모두 성공 시 배열로, 하나라도 실패하면 즉시 reject Promise.all([p1, p2]) .then(([v1, v2]) => console.log(v1, v2)); // 1 2 // allSettled: 성공/실패 관계없이 모두 기다림 Promise.allSettled([p1, p2, p3]) .then(results => results.forEach(r => console.log(r.status))); // fulfilled / fulfilled / rejected // race: 가장 먼저 완료된 결과 반환 // any: 가장 먼저 성공한 결과 반환 (모두 실패 시 AggregateError)
JavaScript
복사

10-3. async / await

// async 함수는 항상 Promise를 반환 async function getUser(id) { return { id, name: '홍길동' }; // Promise.resolve({ id, name }) 와 동일 } async function processOrder(userId) { try { const user = await getUser(userId); // Promise 해결 대기 const orders = await fetchOrders(user.id); // 순차 실행 console.log(`${user.name}의 주문: ${orders.length}`); } catch (err) { console.error('에러:', err.message); } finally { console.log('처리 완료'); } } // 병렬 실행: await를 따로 쓰면 순차, Promise.all로 묶으면 병렬 async function parallel() { // BAD: 순차 실행 (총 2초) const a = await fetchA(); // 1초 const b = await fetchB(); // 1초 // GOOD: 병렬 실행 (총 1초) const [a2, b2] = await Promise.all([fetchA(), fetchB()]); } // 반복문에서의 async async function processAll(items) { // for...of는 await 사용 가능 for (const item of items) { await processItem(item); } // forEach는 await가 동작하지 않음 (주의) // items.forEach(async item => await processItem(item)); // 안 됨 }
JavaScript
복사

11. 이터러블과 제너레이터

11-1. 이터러블 (Iterable)

// Symbol.iterator를 구현하면 for...of, 스프레드, 구조분해에 사용 가능 const range = { from: 1, to: 5, [Symbol.iterator]() { let current = this.from; const last = this.to; return { next() { if (current <= last) { return { value: current++, done: false }; } return { value: undefined, done: true }; }, }; }, }; for (const num of range) { process.stdout.write(num + ' '); // 1 2 3 4 5 } console.log([...range]); // [1, 2, 3, 4, 5]
JavaScript
복사

11-2. 제너레이터 (Generator)

// function*: yield로 값을 하나씩 반환 function* idGenerator() { let id = 1; while (true) { yield id++; // 여기서 실행이 일시 중단됨 } } const gen = idGenerator(); console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 console.log(gen.next().value); // 3 // 실용 예: 무한 스크롤 페이지네이션 function* paginator(fetchFn, pageSize = 10) { let page = 1; while (true) { const data = yield fetchFn(page, pageSize); if (!data || data.length < pageSize) return; // 마지막 페이지 page++; } }
JavaScript
복사

12. 모듈 시스템

// --- math.js --- export const PI = 3.14159; export function add(a, b) { return a + b; } export default class Calculator { multiply(a, b) { return a * b; } } // --- main.js --- import Calculator, { PI, add } from './math.js'; // named + default import * as Math from './math.js'; // 전체 임포트 import { add as plus } from './math.js'; // 별칭 const calc = new Calculator(); console.log(PI); // 3.14159 console.log(add(1, 2)); // 3 console.log(calc.multiply(3, 4)); // 12 // 동적 임포트: 코드 스플리팅, 조건부 로드 async function loadModule() { const { add: dynamicAdd } = await import('./math.js'); console.log(dynamicAdd(10, 20)); // 30 }
JavaScript
복사

13. 에러 처리

// 기본 try-catch-finally try { JSON.parse('잘못된 JSON'); } catch (err) { console.error(err instanceof SyntaxError); // true console.error(err.name); // SyntaxError console.error(err.message); // Unexpected token ... } finally { console.log('항상 실행'); } // 커스텀 에러 class AppError extends Error { constructor(message, code) { super(message); this.name = 'AppError'; this.code = code; } } class NetworkError extends AppError { constructor(statusCode, message) { super(message, 'NETWORK_ERROR'); this.name = 'NetworkError'; this.statusCode = statusCode; } } function fetchApi(url) { if (!url) throw new AppError('URL 없음', 'INVALID_INPUT'); // 서버 에러 시 throw new NetworkError(404, '리소스를 찾을 수 없음'); } try { fetchApi(null); } catch (err) { if (err instanceof NetworkError) { console.log(`네트워크 에러 ${err.statusCode}:`, err.message); } else if (err instanceof AppError) { console.log(`앱 에러 [${err.code}]:`, err.message); } else { throw err; // 예상 못 한 에러는 다시 던짐 } }
JavaScript
복사

14. 고급 패턴

14-1. 구조 분해 + 스프레드 실전 패턴

// 객체에서 특정 키 제외한 나머지 추출 const { password, ...safeUser } = { name: '길동', age: 30, password: '1234' }; console.log(safeUser); // { name: '길동', age: 30 } // 함수 반환값 교환 없이 스왑 let [a, b] = [1, 2]; [a, b] = [b, a]; console.log(a, b); // 2 1
JavaScript
복사

14-2. Map과 Set

// Map: 어떤 타입이든 키로 사용 가능, 삽입 순서 유지 const map = new Map(); map.set('name', '홍길동'); map.set(42, '숫자 키'); map.set({ id: 1 }, '객체 키'); console.log(map.get('name')); // 홍길동 console.log(map.size); // 3 map.delete('name'); for (const [key, value] of map) { console.log(key, value); } // Set: 중복 없는 값 컬렉션 const set = new Set([1, 2, 3, 2, 1]); console.log(set.size); // 3 set.add(4); set.delete(2); console.log([...set]); // [1, 3, 4] // 중복 제거 실전 const unique = [...new Set([1, 1, 2, 2, 3])]; console.log(unique); // [1, 2, 3]
JavaScript
복사

14-3. Proxy와 Reflect

// Proxy: 객체 접근을 가로채어 커스텀 동작 정의 const handler = { get(target, prop) { console.log(`'${prop}' 읽기`); return prop in target ? target[prop] : `${prop}는 존재하지 않음`; }, set(target, prop, value) { if (typeof value !== 'number') { throw new TypeError('숫자만 허용'); } return Reflect.set(target, prop, value); }, }; const obj = new Proxy({}, handler); obj.score = 95; // set 가로채기 console.log(obj.score); // '에 읽기' → 95 console.log(obj.name); // 'name는 존재하지 않음' // obj.name = '문자열'; // TypeError
JavaScript
복사

14-4. WeakMap / WeakRef

// WeakMap: 키가 객체, GC에 의해 키가 수거되면 엔트리도 제거 // → 메모리 누수 없이 객체에 부가 데이터 첨부할 때 사용 const privateData = new WeakMap(); class Person { constructor(name, age) { privateData.set(this, { name, age }); // 외부에서 직접 접근 불가 } greet() { const { name } = privateData.get(this); return `안녕, 나는 ${name}`; } } const p = new Person('길동', 30); console.log(p.greet()); // 안녕, 나는 길동 // p가 GC되면 privateData 엔트리도 자동 제거
JavaScript
복사

15. 최신 문법 정리 (ES2020 ~ ES2024)

// Optional Chaining (ES2020) const user = null; console.log(user?.profile?.avatar); // undefined (에러 없음) // Nullish Coalescing (ES2020) console.log(0 ?? '기본값'); // 0 (0은 null/undefined가 아님) // Promise.allSettled (ES2020) const results = await Promise.allSettled([p1, p2, p3]); // String.replaceAll (ES2021) console.log('a-b-c'.replaceAll('-', '_')); // 'a_b_c' // Object.hasOwn (ES2022) — hasOwnProperty 보다 안전 console.log(Object.hasOwn({ a: 1 }, 'a')); // true // at() — 음수 인덱스 지원 (ES2022) const arr = [1, 2, 3, 4, 5]; console.log(arr.at(-1)); // 5 (마지막 요소) console.log(arr.at(-2)); // 4 // Error cause (ES2022) try { throw new Error('원인 명시', { cause: '네트워크 타임아웃' }); } catch (e) { console.log(e.cause); // '네트워크 타임아웃' } // Array.toSorted / toReversed / toSpliced (ES2023) — 원본 불변 const sorted = [3, 1, 2].toSorted(); // [1, 2, 3] const reversed = [1, 2, 3].toReversed(); // [3, 2, 1] const spliced = [1, 2, 3].toSpliced(1, 1); // [1, 3] // Object.groupBy (ES2024) const items = [ { type: 'fruit', name: '사과' }, { type: 'veggie', name: '당근' }, { type: 'fruit', name: '바나나' }, ]; const grouped = Object.groupBy(items, item => item.type); // { fruit: [...], veggie: [...] }
JavaScript
복사

핵심 요약

주제
핵심 포인트
변수 선언
const 기본, 재할당 필요 시 let, var 사용 지양
타입
typeof, === 엄격 비교, falsy 값 숙지
함수
화살표 함수는 this 바인딩 없음, 클로저로 캡슐화
객체
구조 분해, 스프레드, Object.keys/values/entries
배열
map/filter/reduce 체이닝, 원본 불변 메서드 선호
this
호출 방식에 따라 달라짐, call/apply/bind로 고정
비동기
콜백 → Promise → async/await 순서로 이해
모듈
named exportdefault export, 동적 임포트
에러
커스텀 에러 계층, instanceof로 분기
최신 문법
?., ??, at(), toSorted(), Object.groupBy