지난 포스팅에서 우리는 apply
, call
, bind
에 관해 알아보았다. 이러한 메서드를 사용하여 배열, 문자열, 객체 등 Iterable Object ( 반복 가능한 객체 )를 개별 요소로 분리할 수 있었다. 물론 apply
, call
, bind
를 사용함으로써 그러한 효과를 낼 수 있지만 지금부터 얘기하고자하는 이 스프레드 연산자는 위 메서드보다 더 간결하고 좋은 효과를 낼 수 있다는 점에서 알 필요가 있고, ES6에 추가된 새로운 내용인 만큼 앞으로도 더욱 많이 사용될 것으로 생각된다.
전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소(배열 리터럴의 경우)로 확장하여, 0개 이상의 key-value 쌍으로 객체를 확장시킬 수 있다.
myFunction(...iterableObj);
apply()
대체 일반적으로 배열의 엘리먼트를 함수의 인수로 사용하고자 할때 Function.prototype.apply()
를 사용하였다. (자세한 내용은 이전 포스팅 참고)
function myFunction(x, y, z) {
const addNum = x + y + z;
console.log(addNum); // 3 출력
}
const args = [0, 1, 2];
myFunction.apply(null, args);
다음은 간단하게 myFunction
의 인수 x , y , z 를 더해 addNum
을 호출하는 함수이다. 이 때 인수 x , y , z의 값을 apply
메서드를 이용해 args
배열로 부터 받아왔다. 이전 포스팅에서 다룬 내용이다.
그렇다면 이것을 Spread Operator를 이용해 작성해보자.
function myFunction(x, y, z) {
const addNum = x + y + z;
console.log(addNum);
}
const args = [0, 1, 2];
myFunction(...args); // 나머지 매개변수 이용
가장 위의 함수호출 구문에 의거해서 작성한 코드이다. apply
를 사용한 것 보다 훨씬 간결한 작성법이라 할 수 있다.
function orderNum(x, y, z) {
const addNum = [x, y, z];
console.log(addNum);
}
orderNum(...[1, 2, 3]); // 변수 설정없이 바로 배열 대입
위 코드같이 args라는 인수로 넘겨줄 단일 배열 요소를 만들지 않고 바로 배열형태로 넣는 것 또한 가능하다.
reduce
이용)함수를 실행하는 부분에 스프레드 연산자를 넣는 경우도 ( 앞전 코드 ) 있지만 함수 인자값에서 바로 스프레드 연산자를 사용할 수도 있다.
reduce
함수를 이용해 예제를 확인해보자.
function sum(...theArgs) { // 함수 인자로써 spread operator 사용
return theArgs.reduce((prev, curr) => {
return prev + curr;
});
}
const sum1 = sum(1, 2, 3);
const sum2 = sum(1, 2, 3, 4);
console.log(sum1, sum2); // 6 , 10
new
에 사용new
를 사용해 생성자를 호출 할 때, 배열과 apply
를 직접 사용하는 것은 불가하였다. 하지만, 전개 구문 덕분에 배열을 new
와 함께 쉽게 사용할 수 있게 되었다.
이전 포스팅에서 apply
를 new
구문에 적용시킨 적은 있었지만 그것은 함수의 this
를 받아오기 위한 수단이었고 배열자체에 직접 apply
를 사용할 수는 없었다.
다음 간단한 예시를 보자.
const date = [2022, 4, 3];
const makeDate = new Date(...date);
console.log(makeDate);
new
생성자 인수로 date
배열의 각 단일요소들을 전개 구문을 통해 받아 올 수 있다. 결과를 확인해보면
잘 출력되는 것을 알 수 있다.
이것을 apply
를 사용해 코드를 작성한다면 어떻게 될까?
function infoDate(year, month, day) {
this.year = year;
this.month = month;
this.day = day;
}
function mkDate(year, month, day) {
infoDate.apply(this, [year, month, day]);
return new Date(year, month, day);
}
const addDate = mkDate(2022, 4, 3);
console.log(addDate);
더 쉽게 짤 수 도 있지만 이렇게 new Date를 실행할 함수가 다른 함수로 부터 apply
를 이용해 this
를 받아오고 최종적으로 새로운 변수를 통해 생성하는 식으로 만들 것이다.
전개 구문 없이, 기존의 배열을 결합하는 데 있어서 이전 포스팅에서도 언급하였지만 우리는
push
,concat
등의 메서드를 사용하였다.
우리는 Es6부터 나온 이 Spread operator를 이용해 좀더 깔끔한 배열 병합을 가능하게 할 수 있다.
다음 아주 간단한 예시를 통해 알 수 있다.
const numOne = [1, 2, 3];
const numTwo = [...numOne, 4, 5, 6];
console.log(numTwo); // [1,2,3,4,5,6]
Javascript에서 배열을 새로운 변수에 할당하는 경우 새로운 배열은 기존 배열을 참조한다. 따라서 새로운 배열을 변경하는 경우 원본 배열 역시 변경된다.
다음 간단한 예시를 보자.
const arrOne = ["apple", "banana"];
const arrTwo = arrOne;
arrTwo.push("peach");
console.log(arrTwo); // ['apple', 'banana', 'peach']
console.log(arrOne); // ['apple', 'banana', 'peach']
arrTwo
는 예상대로 기존 배열에 peach
라는 요소가 추가된 배열이 출력되었지만 arrOne
또한 arrTwo
와 동일하게 출력되었다. arrTwo
가 arrOne
을 참조하고, 그 후 arrTwo
를 수정하면서 기존의 참조된 arrOne
배열또한 변경된 것을 확인할 수 있다.
이런 형태의 배열 참조를 원하지 않고, 배열 복사를 위해서는 우린 기존에 slice
또는 Es5 이후 나온 map
을 이용하여 배열 복사를 진행하였다.
⨠ 먼저, slice
를 이용한 배열 복사이다.
코드를 통해 확인해보자.
const students1 = ["John", "Mike"];
const students2 = students1.slice(); //slice 이용
students2.push("Andy");
console.log(students2); // ['John', 'Mike', 'Andy']
console.log(students1); // ['John', 'Mike'] : 기존 배열 그대로 유지
students2
를 변경하여도 배열 복사를 하였기 때문에 기존 students
배열은 변경없이 유지된다.
⨠ 다음으로 map
을 이용한 배열 복사이다.
const students1 = ["John", "Ann"];
const students2 = students1.map((item) => item); // map 사용
students2.push("Judy");
console.log(students2); // ['John', 'Ann', 'Judy']
console.log(students1); // ['John', 'Ann']
마찬가지로 기존 students
배열에는 변화가 없다.
⨠ 그럼 이제 Es6의 Spread 연산자를 사용해보자.
const students1 = ["John", "Ann"];
const students2 = [...students1]; // Spread operator 이용
students2.push("Judy");
console.log(students2); // ['John', 'Ann', 'Judy']
console.log(students1); // ['John', 'Ann']
확실히 코드가 간결해진 것을 확인할 수 있다.
얕은 복제 (prototype 제외) 또는 객체의 병합은 이제
Object.assign()
보다 더 짧은 문법을 사용해 가능해졌다.
Object.assign()
을 이용한 객체 복사⨠ 구문
Object.assign(target, ...sources)
간단한 코드를 통해 확인해보자.
const obj = { a: 1 };
const copy = Object.assign({}, obj); // target 을 빈배열 { }로 한 case
console.log(copy); // { a: 1 }
Spread operator
를 이용한 객체 복사다음 간단한 코드를 통해 구문을 살펴보자.
let currentState = { name: "John", job: "developer" };
currentState = { ...currentState, age: 30 };
console.log(currentState); // {name: 'John', job: 'developer', age: 30}
다음과 같이 객체의 복사는 { ...obj } 를 이용하면 된다.
참고 :
Spread 문법
은 배열을 복사할 때 1레벨 깊이에서 효과적으로 동작한다. 그러므로, 위 예제가 아닌 만약 다차원 배열을 복사하는것에는 적합하지 않을 수 있다. 이것은Object.assign( )
또한 마찬가지이다.
이번 포스팅은 MDN 공식문서의 정의와 예제들을 참조해 작성해보았다. Es6로의 변화 이후 꼭 알면 좋을 기법이라 생각해 포스팅을 작성해보았고 유연하게 잘 사용할 필요가 있다고 생각한다.