시작으로
ES6에서 ...
로 시작하는 형태의 문법이 새롭게 추가되었습니다. ...
로 붙어있는 이 표시는 Spread Opertor
(전개구문, 스프레드 연산자 등)라 부른다.
그리고 Rest Parameter
는 스프레드 연산자를 사용하여 함수의 파라미터를 작성하는 것을 말한다.
Spread Opertor
와 Rest Parameter
는 무엇이고 가독성을 높여주기 위해 어떻게 사용되는지 알아보도록 하자.
Spread Operator
스프레드 연산자를 사용하면 배열, 문자열, 객체 등 반복 가능한 이터러블 객체들을 개별 요소로 분리하여 사용할 수 있다.
기본 문법
// Array
const arr1 = [1,2];
const arr2 = [3,4,5];
console.log([...arr1, ...arr2]); // (5) [1, 2, 3, 4, 5]
console.log([arr1,arr2]);
// Set
const set1 = new Set([1,2]);
const set2 = new Set([3,4,5]);
console.log([...set1, ...set2]); //(5) [1, 2, 3, 4, 5]
// String
const str1 = 'hello';
console.log(...str1); // h e l l o
console.log([...str1]); // (5) ['h', 'e', 'l', 'l', 'o']
// Object
const obj1 = {'name':'seongsik', 'old':20};
const obj2 = {'address': 'seoul'};
console.log({...obj1, ...obj2}); // {name: 'seongsik', old: 20, address: 'seoul'}
// Map
const map1 = new Map([['a',1], ['b',2]]);
console.log(...map1); // (2) ['a', 1] (2) ['b', 2]
원본 복사의 문제해결
javascript에서는 새로운 변수에 할당하는 경우 새로운 변수는 기존 변수를 참조하게 된다. 따라서 새로운 변수를 변경하는 경우 원본 변수도 같이 변경된다.
// Array
const arr1 = [1,2,3];
const arr2 = arr1;
arr2.push(4);
console.log(arr1); // (4) [1, 2, 3, 4]
console.log(arr2); // (4) [1, 2, 3, 4]
// Set
const set1 = new Set([1,2]);
const set2 = set1;
set2.add(3);
console.log(set1); // Set(3) {1, 2, 3}
console.log(set2); // Set(3) {1, 2, 3}
// Object
const obj1 = {'name':'seongsik', 'old':20};
const obj2 = obj1
obj2['address'] = 'seoul';
console.log(obj1); // {name: 'seongsik', old: 20, address: 'seoul'}
console.log(obj2); // {name: 'seongsik', old: 20, address: 'seoul'}
// Map
const map1 = new Map([['a',1], ['b',2]]);
const map2 = map1;
map2.set('c', 3);
console.log(map1); // Map(3) {'a' => 1, 'b' => 2, 'c' => 3}
console.log(map2); // Map(3) {'a' => 1, 'b' => 2, 'c' => 3}
스프레드 연산자를 사용하면 새로운 객체를 생성하기 때문에 원본을 참조하지 않는다.
// Array
const arr1 = [1,2,3];
const arr2 = [...arr1];
arr2.push(4);
console.log(arr1); // (3) [1, 2, 3]
console.log(arr2); // (4) [1, 2, 3, 4]
// Set
const set1 = new Set([1,2]);
const set2 = new Set([...set1]);
set2.add(3);
console.log(set1); // Set(2) {1, 2}
console.log(set2); // Set(3) {1, 2, 3}
// Object
const obj1 = {'name':'seongsik', 'old':20};
const obj2 = {...obj1}
obj2['address'] = 'seoul';
console.log(obj1); // {name: 'seongsik', old: 20}
console.log(obj2); // {name: 'seongsik', old: 20, address: 'seoul'}
// Map
const map1 = new Map([['a',1], ['b',2]]);
const map2 = new Map([...map1]);
map2.set('c', 3);
console.log(map1); // Map(2) {'a' => 1, 'b' => 2}
console.log(map2); // Map(3) {'a' => 1, 'b' => 2, 'c' => 3}
Rest Parameter
함수의 매개변수를 spread operator
로 작성한 형태를 Rest parameter(나머지 매개변수)
라고 부른다.
나머지 매개변수 구문을 사용하면 함수가 정해지지 않은 수의 매개변수를 배열
로 받을 수 있다.
즉, 함수의 파라미터가 몇 개가 됐든 모두 모아서 배열
로 전달한다.
밑의 코드로 이전과 비교하며 이해해보자.
const add1 = (a,b) => a+b;
const add2 = (a,b,c) => a+b+c;
console.log(add1(1,2))
console.log(add2(1,2,3))
기존 javascript
에서는 받을 인자의 개수를 명시적으로 지정하여 함수를 구현했었다면
ES6의 Rest parameter
는 인자의 개수에 상관없이 넘겨주는 인자들을 모두 모아 배열로 받을 수 있게 되었다.
따라서 간결하고 유동적인 코드구현이 가능하다.
const add1 = (...rest) => {
console.log(Array.isArray(rest)); // true
let sum = 0
for(const a of rest) {
sum+=a
}
return sum;
};
console.log(add1(1,2)) // 3
console.log(add1(1,2,3)) // 6
console.log(add1(1,2,3,4)) // 10
단일 인자와 섞어서 사용하기
Rest 파라미터
와 단일 인자들과 섞어서 구현도 가능하다.
앞의 파라미터부터 순서대로 받고 나머지를 Rest 파라미터로 받는다.
function(param1, param2, ...rest){
...
}
밑의 코드를 보면 앞에서부터 인자값을 순서대로 받고 나머지를 Rest 파라미터로 모아 배열로 담는다. 만약에, 나머지 인자값이 없다면 빈 배열로 전달한다.
const test = (param1, param2, ...rest) => {
console.log(`param1 : ${param1}`);
console.log(`param2 : ${param2}`);
console.log(`rest : ${rest}`);
};
/*
* param1과 param2만 받으며 Rest 파라미터는 빈 배열이다.
* param1 : 1
* param2 : 2
* rest :
*/
test(1,2)
/*
* param1과 param2를 받고 나머지 3에 대해서만 Rest 파라미터로 전달
* param1 : 1
* param2 : 2
* rest : 3
*/
test(1,2,3)
/*
* param1과 param2를 받고 나머지 3,4에 대해서만 Rest 파라미터로 전달
* param1 : 1
* param2 : 2
* rest : 3 4
*/
test(1,2,3,4)
arguments VS Rest Parameter
ES5에서도 arguments
객체를 통해 가변 인자 함수를 구현할 수 있다.
arguments
는 Array 형태의 객체이고 Rest 파라미터는 배열이다.
Array 형태의 객체란, arguments가 length 속성과 더불어 0부터 인덱스 된 다른 속성을 가지고 있지만, Array의 forEach, map과 같은 내장 메서드를 가지고 있지 않다는 뜻이다.
function test(){
console.log(arguments)
};
test(1,2) // { '0': 1, '1': 2 }
그렇다면, arguments
와 Rest Parameter
의 차이점은 무엇인가?
간단하게 말하면
-
arguments
는 Array 형태의 객체이기 때문에 배열 내장 함수들을 사용할 수 없다. -
arguments
는 arrow function(화살표 함수)에 바인딩 되지 않는다. 즉, 화살표 함수에 사용할 수 없다. - 따라서, 대부분의 경우에는
Rest Parameter
가 더 좋은 대안으로 사용되고 있다.
const test = ()=> {
console.log(arguments)
};
test(1,2) // Uncaught ReferenceError: arguments is not defined
Rest Parameter는 항상 제일 마지막 매개변수여야 한다.
제목그대로 Rest파라미터는 항상 제일 마지막 파라미터로 사용되어야 한다. 그 이유는 나머지를 전부 rest로 사용하기 때문에 뒤에 파라미터가 있다면 할당할 수 없기 때문이다.
const test=(...rest, param1, param12) => {
console.log(rest);
console.log(param1);
console.log(param12);
}
test(1,2,3,4,5) // Uncaught SyntaxError: Rest parameter must be last formal parameter
정리해서
- Spread 연산자는 배열, 문자열, 객체 등 반복 가능한 이터러블 객체들을 개별 요소로 분리하여 사용할 수 있다.
- Spread 연산자를 이용해 복제하게되면 새로운 객체를 생성하여 원본 객체를 참조하지 않는다.
- Rest Parameter는 함수 선언문의 파라미터에 Spread(…) 연산자를 이용하여 작성하여 가변 인자들을 모아 배열로 전달받는 것이다.
- Rest Parameter는 단일 인자들과 섞어서 사용할 수 있다. 이를 통해 유연한 가변 인자 함수를 구현할 수 있다.
// 예제 1
const test = (x, ...rest) => {
console.log(x); // 1
console.log(rest); // (2) [2,3]
}
test(...[1, 2, 3]);
// 예제 2
const test = (x,y,z) => {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}
test(...[1, 2, 3]);
// 예제 3
const test = (x, ...rest) => {
console.log(x); // first param
console.log(rest); // (3) [1, 2, 3]
}
test('first param', 1, 2, 3);