[JavaScript] 전개 연산자
JavaScript
2021.01.18
정의
- ECMAScript6(2015)에서 새로 추가된 전개 연산자(Spread Operator)란 객체나 배열의 값을 하나 하나 넘기는 용도로 사용할 수 있다.
- 직관적이고, 배열의 아무곳에 추가 가능하다.
- 전개 구문 (spread 프로퍼티인 경우 제외) 은 iterable 객체에만 적용 가능하다.
- 이터러블(iterable)은 Array, String, Map, Set, DOM구조
- iterator를 생성해서 next()로 순회할 수 있는 자료구조가 이터러블이라고 생각하면 됨!
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
// ES5
const arrWrap = arr1.concat(arr2, arr3);
console.log(arrWrap); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// ES6
const arrWrap2 = [...arr1, ...arr2, ...arr3];
console.log(arrWrap2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
구문
- 함수 호출
myFunction(...iterableObj);
- 배열 리터럴과 문자열
[...iterableObj, '4', 'five', 6];
- 객체 리터럴(ECMAScript 2018에서 추가):
let objClone = {...obj};
예제
함수 호출에서의 전개
-
apply()
대체-
일반적으로 배열의 엘리먼트를 함수의 인수로 사용하고자 할 때
Function.prototype.apply()
를 사용했었다.function myFunction(x, y, z) {} var args = [0, 1, 2]; myFunction.apply(null, args); // 전개 구문을 사용해 ▲ 코드는 ▼과 같이 작성될 수 있다. function myFunction(x, y, z) {} var args = [0, 1, 2]; myFunction(...args);
-
인수 목록의 모든 인수는 전개 구문을 사용할 수 있으며, 여러번 사용될 수 있다.
function myFunction(v, w, x, y, z) {} var args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
-
-
new
에 적용new
를 사용해 생성자를 호출 할 때, 배열과apply
를 직접 사용하는 것은 불가능했었다.
전개 구문은 배열을new
와 함께 쉽게 사용될 수 있다.var dateFields = [1970, 0, 1]; // 1 Jan 1970 var d = new Date(...dateFields);
배열 리터럴에서의 전개
-
더 강력한 배열 리터럴
- 전개 구문 없이, 이미 존재하는 배열을 일부로 하는 새로운 배열을 생성하기에, 배열 리터럴 문법은 더 이상 충분하지 않으며
push(), splice(), concat() 등의 조합을 사용하는 대신 명령형 코드를 사용해야 했다. 전개 구문으로 이는 훨씬 더 간결해졌다.var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]
인수 목록을 위한 spread 처럼, ... 은 배열 리터럴의 어디에서든 사용될 수 있으며 여러번 사용될 수도 있다.
- 전개 구문 없이, 이미 존재하는 배열을 일부로 하는 새로운 배열을 생성하기에, 배열 리터럴 문법은 더 이상 충분하지 않으며
-
배열 복사
-
Spread 문법은 배열을 복사할 때 1 레벨 깊이에서 효과적으로 동작함.
var arr = [1, 2, 3]; var arr2 = [...arr]; // arr.slice() 와 유사 arr2.push(4); // arr2 은 [1, 2, 3, 4] 이 됨 // arr 은 영향을 받지 않고 남아 있음
-
위 예제와 달리 이 예제와 같이 다차원 배열을 복사하는것에는 적합하지 않을 수 있음.
var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // 이제 배열 a 도 영향을 받음: [[], [2], [3]]
-
-
배열을 연결하는 더 나은 방법
Array.prototype.concat()
은 배열을 존재하는 배열의 끝에 이어붙이는데 종종 사용된다.- 전개 구문 없이 사용
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // arr2 의 모든 항목을 arr1 에 붙임 arr1 = arr1.concat(arr2);
- 전개 구문 사용
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2]; // arr1 은 이제 [0, 1, 2, 3, 4, 5]
- 전개 구문 없이 사용
Array.prototype.unshift()
는 존재하는 배열의 시작 지점에 배열의 값들을 삽입하는데 종종 사용된다.- 전개 구문 없이 사용
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // arr2 의 모든 항목을 arr1 의 앞에 붙임 Array.prototype.unshift.apply(arr1, arr2); // arr1 은 이제 [3, 4, 5, 0, 1, 2] 가 됨
- 전개 구문 사용
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; // arr1 은 이제 [3, 4, 5, 0, 1, 2] 가 됨
- 전개 구문 없이 사용
객체 리터럴에서의 전개
-
얕은 복제(prototype 제외) 또는 객체의 병합은 이제 Object.assign() 보다 더 짧은 문법을 사용해 가능.
var obj1 = {foo: 'bar', x: 42}; var obj2 = {foo: 'baz', y: 13}; var clonedObj = {...obj1}; // Object { foo: "bar", x: 42 } var mergedObj = {...obj1, ...obj2}; // Object { foo: "baz", x: 42, y: 13 }
-
아래 예제를 보면, 전개 구문은 예상대로 동작하지 않음! 나머지 매개변수로 인해, 인수 배열을 객체 리터럴로 전개한다.
var obj1 = {foo: 'bar', x: 42}; var obj2 = {foo: 'baz', y: 13}; const merge = (...objects) => ({...objects}); var mergedObj = merge(obj1, obj2); // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } } var mergedObj = merge({}, obj1, obj2); // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
-
객체 리터럴에서의 전개 연산자는..
- Object.assign() 은 setters 를 트리거하지만 전개 구문은 그렇지 않음을 유의.
- Object.assign() 함수를 대체하거나 흉내낼 수 없음을 유의.
기타..(ETC)
Set 객체를 Array로 변환하는 방법
-
Array.from()
Array.from 함수는 유사배열객체(array-like object)나 반복가능객체(iterable object)를
얕은 복사(shallow copy)하여 새로운 배열(Array) 객체를 만들어줌- 유사배열객체(array-like object) : length 속성과 index element를 가지는 객체
- 반복가능객체(iterable object) : 배열을 일반화한 객체 ex)Map, Set
const set = new Set([1, 2, 3]); const arr = Array.from(set); console.log(Array.isArray(arr)); // true console.log(arr); // [1, 2, 3]
-
Spread Operator(전개 연산자)
Spread Operator는 ES6의 문법으로 배열이나 문자열과 같이 반복가능한 객체를 하나씩 펼쳐서 리턴.
'...'과 같이 점 3개로 표시함.const set = new Set([1, 2, 3]); const arr = [...set]; console.log(Array.isArray(arr)); // true console.log(arr); // [1, 2, 3] // 전개 연산자(...) 사용하여 Set 객체의 값들을 하나씩 꺼내서, 새로운 배열의 원소로 넣어서, arr 변수에 저장함
-
forEach
const set = new Set([1, 2, 3]); const arr = []; set.forEach((element) => { arr.push(element); }); console.log(Array.isArray(arr)); // true console.log(arr); // [1, 2, 3]
참고 자료