본문으로 건너뛰기
김신건의 로그

[Javascript] Spread / Rest

· 수정 · 📖 약 1분 · 198자/단어 #javascript #spread #rest #syntax
JS Spread, JS Rest, JS Spread / Rest, ...연산자, 전개 연산자

정의

같은 문법 ... 가 두 가지 의미.

  • Spread : iterable 을 펼침 (right-hand)
  • Rest : 나머지를 모음 (left-hand 또는 함수 매개변수)

Spread (펼침)

배열

const a = [1, 2];
const b = [...a, 3, 4];        // [1, 2, 3, 4]
const c = [0, ...a, ...a];     // [0, 1, 2, 1, 2]
const copy = [...a];            // 얕은 복사

// 함수 인자
Math.max(...[1, 2, 3]);         // 3
console.log(...['a', 'b']);     // a b

// string 도 iterable
[...'abc']                       // ['a', 'b', 'c']

객체 (ES2018+)

const a = { x: 1, y: 2 };
const b = { ...a, z: 3 };       // { x: 1, y: 2, z: 3 }
const copy = { ...a };           // 얕은 복사

// 병합 + override
const merged = { ...defaults, ...userInput };
// userInput 이 defaults 를 덮어씀

Rest (모음)

함수 매개변수

function sum(...nums) {
    return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4);            // 10

// 일부 인자 + rest
function logger(level, ...messages) {
    console.log(`[${level}]`, messages.join(' '));
}
logger('INFO', 'a', 'b', 'c');

배열 destructuring

const [first, ...others] = [1, 2, 3, 4];
// first = 1, others = [2, 3, 4]

const [a, b, ...rest] = arr;

객체 destructuring

const { name, ...rest } = user;
// name = user.name, rest = 나머지 모든 속성

arguments vs rest

// 옛 스타일
function foo() {
    console.log(arguments);    // 유사 배열 (array-like)
    Array.from(arguments).map(...);   // 변환 필요
}

// 모던
function foo(...args) {
    console.log(args);          // 진짜 배열
    args.map(...);              // 바로 메서드
}

arguments 는 화살표 함수에서 안 됨, rest 는 됨.

자주 쓰는 패턴

배열 복사

const original = [1, 2, 3];
const copy = [...original];     // 얕은 복사
// 또는: Array.from(original), original.slice()

객체 복사

const copy = { ...original };   // 얕은 복사
// 깊은 복사는 structuredClone(original)

객체 병합

const config = { ...defaults, ...userOptions };

객체에서 특정 키 제외

const { password, ...safe } = user;     // safe 는 password 없는 user

배열 끝/처음 추가

const newArr = [...arr, newItem];        // 끝
const newArr2 = [newItem, ...arr];       // 처음

immutable 갱신.

Math 함수 + 배열

const max = Math.max(...arr);
const min = Math.min(...arr);

함정

1. 얕은 복사

const a = [{ x: 1 }];
const b = [...a];
b[0].x = 99;
a[0].x      // 99 (참조 공유)

깊은 복사는 structuredClone(obj) (ES2022+) 또는 JSON.parse(JSON.stringify(obj)) (제한적).

2. 객체 spread 의 순서

const a = { x: 1 };
const b = { x: 99, ...a };       // { x: 1 }  (뒤가 우선)
const c = { ...a, x: 99 };       // { x: 99 } (뒤가 우선)

같은 키는 뒤에 오는 값이 우선.

3. iterable 만 spread

[...{ a: 1 }]      // ❌ TypeError (객체는 iterable 아님)
{ ...[1, 2, 3] }   // { 0: 1, 1: 2, 2: 3 } (배열을 객체로)

4. rest 의 위치

function foo(...args, last) {}    // ❌ SyntaxError (rest 는 마지막)
function foo(first, ...rest) {}    // ✓

5. Symbol.iterator 가 없으면

const obj = { length: 3 };
[...obj]    // ❌ TypeError

Symbol.iterator 가 있는 객체만 array spread 가능.

참고

이 글의 용어 (3개)
[Javascript] Arrayjavascript
정의 JavaScript 의 는 순서 있는 객체. 정수 키 + . 풍부한 메서드 (map/filter/reduce/...) 가 함수형 스타일을 지원. 생성 핵심 메서드 (반복) …
[Javascript] Destructuringjavascript
정의 Destructuring 은 배열 또는 객체의 일부를 변수로 풀어내는 ES6 문법. 코드를 짧고 명시적으로. 객체 배열 함수 매개변수 자주 쓰는 idiom API 응답 분해…
[Javascript] Objectjavascript
정의 JavaScript 의 는 key-value 쌍의 컬렉션. 거의 모든 non-primitive 값이 객체. 함수, 배열, 정규식도 객체. 생성 접근 수정 / 삭제 Objec…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기