[JavaScript] Spread Syntax, Rest Parameter, arguments 정리

이제는 더이상 헷갈려 하고 싶지 않다...

1. Spread Syntax (...)

Spread Syntax는 쉽게 말해, 배열, 객체, 문자열의 요소를 모두 꺼내준다.

1) 함수의 인자로 들어가는 Spread Syntax

function func(x, y, z) { // x=arr[0] y=arr[1] z=arr[2]
	return x+y+z;
}
const arr = [1, 2, 3]
console.log(func(...arr)); // arr의 요소들이 func의 인수로 확장된다

// expected result
// 6

2) 배열 리터럴에서의 전개

Spread Syntax가 도입되면서, push(), splice(), concat() 등을 사용하지 않고 훨씬 간결하게 배열을 합칠 수 있게 되었다.

const eng = ['hi', 'bi', 'jazz'];
const lang = ['안녕', '잘있어', '재즈', ...eng];
// ['안녕', '잘있어', '재즈', 'hi', 'bi', 'jazz']

배열과 배열을 합칠 수도 있다.

const math = ['plus', 'minus'];
const lang = ['korean', 'swedish'];
const study = [ ...math, ...lang]; // ['plus', 'minus', 'korean', 'swedish']

또한, Spread Syntax로 배열을 간편하게 복사할 수 있다. 이 때 Spread Syntax는 배열의 요소들을 확장하여 새로운 배열에 담기 때문에, 얕은 복사가 이루어진다.

아래의 예제를 보자.

const eng = ['hi', 'bi', 'jazz'];
const newEng = [...eng]; // eng 배열의 요소들이 확장되어 담긴다
newEng.push('rock');

console.log(eng);    // ['hi', 'bi', 'jazz']
console.log(newEng); // ['hi', 'bi', 'jazz', 'rock']

newEng에는 Spread Syntax를 이용해 eng의 요소들을 복사하였다. newEngeng의 요소들을 가지고 있지만, 서로 다른 주소값을 참조하는 별개의 배열이 되었다. 따라서 newEng에 새로운 요소를 추가해도 eng에는 아무런 변화가 없는 것을 확인할 수 있다.

[주의!]
다차원 배열을 복사할 때는 조심해야 한다. 복사하는 요소가 배열인 경우, 그 주소를 복사한다. 다시 말해, 배열 형태의 요소는 깊은 복사를 한다. 다음의 예제를 보자.

const oldNum = [1, [2, 3], 3];
const newNum = [...oldNum];
newNum[1][1] = 4;  
console.log(oldNum); // [1, [2, 4], 3]

newNum[1]oldNum[1]이 가진 [2, 3] 배열의 주소값을 가진다. 그러면 oldNum[1]newNum[1]은 같은 배열을 참조하게 된다. 따라서 newNum[1]이 참조하는 배열의 요소를 변경하게 되면, oldNum[1]도 같은 배열을 참조하기 때문에 영향을 미치게 된다.
따라서 다차원 배열을 복사할 때는 배열 요소가 깊은 복사 된다는 점을 유의해야 한다!

3) 객체 리터럴에서의 전개

ECMAScript2018부터 객체에도 Spread Syntax를 사용할 수 있게 되었다. 키값쌍을 확장할 수 있다.

const guest1 = { name: 'youjin', age: 25 };
const guest2 = { name: 'nittre', human: true };

const guest3 = { ...guest1 };  
// { name: 'youjin', age: 25}

Spread Syntax를 이용해 다수의 객체를 복사하는 경우, 키가 겹치면 기존 키 값을 덮어쓴다.

const group = { ...guest1, ...guest2 }; 
// { name: 'nittre', age: 25, human: true }

비슷한 작업을 Object.assign() 메서드를 이용해 실행할 수도 있다.

Object.assign(target_obj, source_obj) 메서드
target_obj 객체에 source_obj의 속성을 복사하고, 복사된 target_obj를 리턴한다.

let target = {a: 1, b: 2};
let source = {b:3, c: 5};
let returnTarget = Object.assign(target, source);
console.log(returnTarget);  //{a: 1, b: 3, c: 5}
console.log(target);        //{a: 1, b: 3, c: 5}

다만, Spread Syntax를 사용하는 경우 원본 객체가 변하지 않지만, Object.assign() 메서드를 사용하면 원본 객체가 변한다.

[주의]
객체 spread Syntax는 객체에서만 가능하다.

const a_obj = {a: 1};
const arr = [...a_obj];
// Uncaught TypeError: a_obj is not iterable

2. Rest Parameter

Rest Parameter는 함수의 인수를 배열로 나타낼 수 있게 해준다. 함수의 마지막 파라미터의 앞에 ...를 붙여, 함수의 인수들 중 특정 인자에 대입되지 않은 남은 인수들(rest parameters)을 하나의 배열로 묶는다.

function sumOfNums(name, ...args){
  // name에는 첫번째 인수가 들어가며
  // 나머지 인수들은 args 배열에 들어간다
  let sum = 0;
  for (let el of args){
  	sum += el;
  }
  return `${name}: ${sum}`
};

console.log(sumOfNums('from 1 to 4', 1, 2, 3, 4)); // 'from 1 to 4: 10'

구조 분해 할당을 이용해 Rest Parameter를 해체할 수도 있다.

function func(...[a, b, c]){
  return a+b+c;
}

f(1);			// NaN (b와 c가 undefined이기 때문)
f(1, 2, 3);		// 6
f(1, 2, 3, 4);  // 6 (네번째 파라미터는 해체되지 않음)

Spread Syntax와 Rest Parameter의 차이
Spread Syntax는 배열을 다른 요소로 확장하는 반면, Rest Parameter는 여러 요소를 수집하여 하나의 요소로 압축한다.

3. arguments 객체

arguments 객체는 함수의 인수를 참조하는 유사 배열 객체이다.

키는 함수의 인수 순서에 따른 인덱스이다.

function func(a, b, c) {
  /*
  arguments는 다음과 같은 객체가 된다.
  {  "0": 'hi',
  	 "1": 'i am',
     "2": 'nittre'
  }
  */
 	console.log(arguments[0]);   // 'hi'
    console.log(arguments[1]);   // 'i am'
    console.log(arguments[2]);   // 'nittre'
}

func('hi', 'i am', 'nittre');

arguments 객체는 유사 배열 객체로, Array와 비슷하지만 length 속성만을 쓸 수 있으며, push(), pop() 등의 배열 메서드는 사용할 수 없다.

arguments 객체를 배열로 만들고 싶다면, 다음과 같은 방법을 사용할 수 있다.

// 1. Array.from() 메서드 사용
let args = Array.from(arguments);

// 2. Spread Syntax 사용
let args = [...arguments];  
/* 배열 안에서 객체에 Spread Syntax를 사용할 수 없지만,
arguments 객체는 유사배열이기 때문에 가능하다 */

유사 배열 객체length 속성과 인덱싱된 요소를 가진 객체를 의미한다. 문자열(String)도 유사 배열 객체라고 할 수 있다.

Array.from() 메서드
Array.from() 메서드는 유사 배열 객체나 이터러블 객체를 얕게 복사하여 새로운 배열을 만든다.

Array.from('foo');
// ['f', 'o', 'o']

4. Spread Syntax, Rest Parameter와 arguments의 차이

  1. Spread Syntax는 배열(또는 객체, 문자열)의 요소를 확장하는 개념이라면, Rest Parameter와 arguments는 흩어진 함수의 인자를 압축하는 개념이다.
  2. Rest Parameter는 함수 표현에 정식으로 정의되지 않은 나머지 인자들을 대상으로 하는 반면, arguments 객체는 모든 함수 인자를 대상으로 한다.
  3. arguments 객체는 유사 배열 객체인 반면, Rest Parameters로 만들어진 배열은 Array 인스턴스이다.

참고

  1. MDN - 전개구문
  2. MDN - Rest 파라미터
  3. MDN - arguments 객체
  4. MDN - Array.from()

좋은 웹페이지 즐겨찾기