0927 - 1003
0927
56일 차
1교시
deep copy를 언제 사용해야할까?
매개변수로 참조를 받아서 부수효과를 발생시키고 싶지 않을 때 새로운 값을 생성해서 반환
JSON
http 통신에서 모든 데이터는 아스키 코드로 보내고 받아야한다. 객체처럼 생긴 JSON이라는 문자열 포맷을 http 아스키코드로 보낸다. -> 서버 통신할 때 사용
자바스크립트에서의 객체 지향형
자바스크립트에서 객체지향은 문제가 있다.
ex) 메서드내에서 this는 동적으로 바인딩되어 의도치 않게 동작 가능하다.
함수형에서는 메서드를 최대한 작성하지 않고, 함수로 프로퍼티를 참조한다.
-> 이렇게 되면 응집도가 떨어지게 되는데, 이를 극복하기 위해 모듈을 클래스처럼 사용한다.
2교시
클로저를 만들 때는 외부함수를 즉시실행함수로 만들어야 한다.
-> 하나의 렉시컬 환경을 여러 개의 클로저가 공유하기 위해서
정보 은닉과 결합도는 연관을 가지고 있다. 정보 은닉은 꼭 필요한 애들만 알려주겠다 라는 뜻
모듈 패턴을 사용하는 이유?
-> 응집도를 높이기 위해서
3교시
클래스는 기본적으로 선언문으로 작성하는 것이 일반적
접근자 프로퍼티는 객체 리터럴과 클래스에서 사용 가능. 생성자 함수에서는 사용이 불가능하다.
생성자 함수를 쓰느니 클래스를 쓰는 것이 낫다.
-> 자료구조를 만들 때만 사용
4교시
자바스크립트 배열은 배열이 아니다.
자료구조에서 말하는 배열은 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료 구조이다.
배열을 만들 때 배열처럼 만들어야 최적화가 잘 된다.
-> 빈틈없이 동일한 데이터 타입으로
5교시
원본 배열을 직접 변경하는 메서드를 mutator 메서드, 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하는 메서드를 accessor 메서드라고 한다.
-> accessor 메서드 위주로 사용하자
0928
57일 차
깃 수업
프론트엔드-2기 전반적인 피드백
- 제목만 존재하는 커밋 -> 짧더라도 커밋단위에 대한 설명을
- 제목이 불친절한 커밋 -> 클릭을 안해도 어떤 내용인지 알 수 있는 충분한 요약설명
- 큰 커밋단위 -> 수업내용의 경우 수업 진행단위 별로 잘라 커밋
- 브랜치에 대한 적극적 활용에 대한 아쉬움 -> 수업 모듈별로 브랜치 나누어 작성한 뒤, 해당 브랜치 push까지
- resolved, closed, fixed -> 커밋할 때 적어주면 이 커밋이 이슈를 해결했다고 알려준다.
- 릴리즈 시, 태그 커밋이 릴리즈 노트가 되는 부분이므로 잘 작성해야 한다.
이분탐색
이분탐색 알고리즘 학습을 하면서 주어졌던 문제를 다시 풀어보고, 잊어버렸던 개념들을 다시 머리속에 넣었다.
우선 이분탐색 알고리즘은 lt와 rt의 인덱스를 설정하고, while문 내부에서 lt 가 rt보다 작거나 같을 때까지 반복하여 lt와 rt의 중간값을 구한다.
그리고 필요에 따라 lt와 rt의 값을 조절해가며 원하는 값을 얻는 알고리즘이다. 알고리즘 자체는 쉽지만, 원하는 값을 얻는 로직을 짜기 위해서 아이디어가 필요하다는 생각이 들었다.
프로그래머스 Level3 - 입국심사
function solution(n, times) {
let answer = 0;
lt = 0;
rt = n * times[times.length - 1];
function count(t) {
let cnt = 0;
for (let x of times) {
cnt += Math.floor(t / x);
}
return cnt;
}
while (lt <= rt) {
let mid = parseInt((lt + rt) / 2);
if (count(mid) >= n) {
rt = mid - 1;
answer = mid;
} else {
lt = mid + 1;
}
}
return answer;
}
- mid로 값을 구하는 함수를 작성하는데 좀 더 문제를 잘 이해하고 시도해야겠다는 생각이 들었다. 문제를 잘못 파악하여 삽질하는 시간이 꽤나 길어져버렸다.
- 이 문제에서 실수했던 요인중 하나가 rt 값을 충분하게 잡았다고 생각하고 문제를 풀었는데, 생각보다 더 큰 rt의 값이 필요했다. 이 문제 때문에 테스트케이스 절반밖에 맞지 못했고, rt의 값을 좀 더 고민해서 잡아야겠다고 생각했다.
프로그래머스 Level2 - 큰 수 만들기
function solution(number, k) {
let answer = "";
let arr = [];
let cnt = 0;
for (let i = 0; i < number.length; i++) {
while (arr.length && arr[arr.length - 1] < number[i] && cnt < k) {
arr.pop();
cnt++;
}
if (arr.length < number.length - k) arr.push(number[i]);
}
answer = arr.join("");
return answer;
}
- 아이디어를 생각해내기가 쉽지 않은 문제였다.
- 순서를 고정한 채로 가장 큰 수를 만들어내야 하므로, 새로 들어오는 값보다 기존 값이 작으면서 배열이 비어있지 않고 뺀 개수가 k보다 작다면 값을 뺐다. 그 외에는 push
- 그리고나서도 tc 하나에 걸렸는데, 이는 그외의 경우에 모두 push 해주므로 발생한 문제이다. 배열의 길이가 목표 값만큼 찼다면 더이상 push 하지 말아야 한다.
0929
58일 차
투포인터
조금 까다롭고 쉽지 않다고 생각되는 유형의 투포인터 문제가 있어서 정리하고자 한다.
연속 부분수열 3
N개의 수로 이루어진 수열이 주어집니다. 이 수열에서 연속부분수열의 합이 특정숫자 M이하가 되는 경우가 몇 번 있는지 구하는 프로그램을 작성하세요. 만약 N=5, M=5이고 수열이 다음과 같다면 13123 합이 5이하가 되는 연속부분수열은 {1}, {3}, {1}, {2}, {3}, {1, 3}, {3, 1}, {1, 2}, {2, 3}, {1, 3, 1}로 총 10가지입니다.
function solution(nums, m) {
let answer = 0;
let lt = 0;
let sum = 0;
for (let rt = 0; rt < nums.length; rt++) {
sum += nums[rt];
while (sum > m) {
sum -= nums[lt++];
}
answer += rt - lt + 1;
}
return answer;
}
- 예전에 풀었던 문제지만, 오랜만에 다시 풀어보니 전혀 감이 잡히지 않아서 다음에 풀었을 때는 막히지 않기 위해 한 번 더 정리한다.
- 이 문제의 핵심 개념은 일단 rt에서는 무조건 어떤 일을 수행하고, 조건에 어긋났을 때 while 문으로 문제가 해결될 때까지 lt를 조정하는 것이다.
- 그 상태로 answer에 필요한 작업을 진행한다. (조건이 완성된 채)
이 문제와 비슷한 식의 방법을 적용하는 문제를 마주쳤다.
최대 길이 연속부분수열
0과 1로 구성된 길이가 N인 수열이 주어집니다. 여러분은 이 수열에서 최대 k번을 0을 1로 변경할 수 있습니다. 여러분이 최대 k번의 변경을 통해 이 수열에서 1로만 구성된 최대 길이의 연속부분수열을 찾는 프로그램을 작성하세요. 만약 길이가 14인 다음과 같은 수열이 주어지고 k=2라면 11001101101101 여러분이 만들 수 있는 1이 연속된 최대 길이의 연속부분수열은 1 1 0 0 1 1 1 1 1 1 1 1 0 1 이며 그 길이는 8입니다.
function solution(nums, k) {
let answer = 0;
let lt = 0;
let cnt = 0;
for (let rt = 0; rt < nums.length; rt++) {
if (nums[rt] === 0) cnt++;
while (cnt > k) {
if (nums[lt] === 0) cnt--;
lt++;
}
answer = Math.max(answer, rt - lt + 1);
}
return answer;
}
- 위의 문제와 비슷한 방법으로 우선 rt에서는 0일 때 바꾼 횟수를 증가시키고, lt에서는 cnt가 필요 이상 증가하면 줄여준다.
- 그리고 rt와 lt를 이용해 정답을 도출한다.
- 연속부분수열 관련 문제에서는 투포인터 알고리즘을 가장 먼저 떠올려야겠다.
0930
59일 차
위클리 문제 1번
function solution(nums, k) {
let answer = 0;
let sum = 0;
let nH = new Map();
for (let i = 0; i < nums.length; i++) {
if (nums[i] % 2 === 1) sum++;
if (sum === k) answer++;
if (nH.has(sum - k)) answer += nH.get(sum - k);
nH.set(sum, nH.get(sum) + 1 || 1);
}
return answer;
}
console.log(solution([1, 2, 1, 1, 2], 2));
console.log(solution([2, 2, 2, 1, 2, 2, 1, 2, 2, 2], 2));
console.log(solution([2, 4, 6], 1));
- 연속 부분수열 문제
- 투포인터 알고리즘을 떠올리고 문제를 해결해보려고 했으나 생각처럼 잘 되지 않는 부분이 있었다.
- 어디까지의 연속 부분 수열 내에서 특정 값이 되는 경우에는 이런 방식을 적용해서 문제를 해결해야겠다.
위클리 문제 2번
function solution(s, e) {
let answer = 0;
function BFS() {
const queue = new Set();
queue.add(s);
let L = 0;
while (queue.size) {
e += L + 1;
L++;
if (queue.has(e)) return L;
for (let v of [...queue]) {
for (let nx of [v + 1, v - 1, v * 2]) {
if (nx === e) {
return nx > 500000 ? -1 : L;
}
if (nx <= 500000 && nx > 0) {
queue.add(nx);
}
}
}
}
return -1;
}
answer = BFS();
return answer;
}
console.log(solution(5, 6));
console.log(solution(10, 3));
console.log(solution(1, 11));
- 시험을 볼 때 테스트케이스를 모두 통과했지만 풀이가 완벽하지는 않았다는 사실을 깨달았다.
- bfs에서 체크 배열을 사용하지 않으면서 중복을 피하고 싶은 경우 set을 활용해 문제를 해결할 수 있다.
1001
60일 차
1교시
코드에 대한 이해가 없으면 디버깅을 할 때 브레이크 포인트를 잡기도 힘들다.
2교시
forEach에서 리턴하는 행위는 아무런 의미가 없다.
-> continue도 안하고 break도 안하는 경우에 사용
map은 호출한 배열와 length가 같다. 그 말은 길이가 같은 경우 map을 사용하면 대부분 해결이 된다.
filter는 호출한 배열의 length 보다 같거나 작다.
reduce의 결과는 하나가 된다.
스프레드 문법은 뒤에 이터러블이 와야 한다.
이터러블의 종류로는 배열, string, map, set 등이 있다.
slice()를 사용한 복사와 스프레드 문법을 사용한 복사 중에서는 후자가 좋다.
스프레드 문법은 표현식이기 때문에 오류가 발생할 확률이 줄어들고 사용이 간편한다.
객체 안에서 스프레드 문법으로 객체를 풀면 복사와 같은 효과를 낸다. -> best practice
4교시
forEach는 보통 외부의 것을 mutate하기 때문에 안 쓰는 것이 좋다.
-> map 사용
사용 순위
map, filter -> reduce -> forEach
reduce는 map이랑 filter에 비해 가독성이 떨어진다.
꿀팁
- map이나 filter를 사용할 때 첫 번째 인자로 요소를 받아올 때, 디스트럭처링 할당을 사용하면 더 가독성 있게 코드 작성이 가능하다.
- 템플릿 리터럴에 Html을 작성하는 경우 코드 상에서 가독성만 고려하면 된다.
-> 어차피 이동하면 같아지기 때문에 개발 상에서 가독성만 고려 sort()
사용 시 원본 배열을 변경하기 때문에 이 점을 고려해서 스프레드 문법으로 배열을 복사하여 반환해야 한다.- 또한 문자일 때와 숫자일 때 모두를 고려하여 비교 연산자를 사용해 비교해서 1이나 -1을 반환해준다.
- 이 때, 값이 같은 경우는 바뀌지 않도록 처리해준다.
- 객체에서 프로퍼티를 변환해서 반환해줘야 하는 경우, 새로운 객체 리터럴에 디스트럭처링 할당을 사용하고 바꿔야하는 프로퍼티를 변경해서 반환해주면 코드가 줄어든다.
프로그래머스 카카오 Level1 - 실패율
function solution(N, stages) {
const answer = [];
const nh = new Map();
let total = stages.length;
for (let x of stages) {
nh.set(x, (nh.get(x) || 0) + 1);
}
for (let i = 1; i <= N; i++) {
let fail = (nh.get(i) || 0) / total;
answer.push([fail, i]);
total -= nh.get(i) || 0;
}
return answer.sort((a, b) => b[0] - a[0]).map((v) => v[1]);
}
console.log(solution(5, [2, 1, 2, 6, 2, 4, 3, 3]));
console.log(solution(4, [4, 4, 4, 4, 4]));
1002
34장 이터러블
이터레이션 프로토콜
이터레이션 프로토콜은 순회 가능한 데이터 컬렉션을 만들기 위해 ECMAScript 사양에 정의하여 미리 약속한 규칙이다.
ES6에서는 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 for …of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화했다.
- 이터러블 프로토콜
- Well-known Symbol인 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속 받은 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다.
- 이터러블 프로토콜을 준수한 객체를 이터러블이라 한다.
- 이터레이터 프로토콜
- 이터레이터는 next 메서드를 소유하며 next 메서드를 호출하면 이터러블을 순회하며 value와 done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다.
- 이터레이터 프로토콜을 준수한 객체를 이터레이터라 한다.
- 이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할을 한다.
이터러블
- Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체
- for …of 문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.
- 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
- 일반 객체는 for …of 문과 배열 디스트럭처링 할당의 대상으로 사용할 수 없지만, 스프레드 프로퍼티 제안은 일반 객체에 스프레드 문법을 허용한다.
const obj = { a: 1, b: 2 };
console.log({ c: 3, ...obj });
// { c: 3, a: 1, b: 2 }
이터러블인지 확인하는 함수
const isIterable = (v) =>
v !== null && typeof v[Symbol.iterator] === "function";
이터레이터
- 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다. 이터레이터는 next 메서드를 갖는다.
- next 메서드가 반환하는 이터레이터 리절트 객체의 value 프로퍼티는 현재 순회 중인 이터러블의 값을 나타내며 done 프로퍼티는 이터러블의 순회 완료 여부를 나타낸다.
빌트인 이터러블
JS는 이터레이션 프로토콜을 준수한 객체인 빌트인 이터러블을 제공한다.
- Array
- String
- Map
- Set
- TypeArray
- arguments
- DOM 컬렉션
- NodeList.prototype
- HTMLCollection.prototype
for … of 문
순회하면서 이터러블의 요소를 변수에 할당한다.
for (변수선언문 of 이터러블) { ... }
- 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 리절트 객체의 value 프로퍼티 값을 for … of 문의 변수에 할당한다.
- done 프로퍼티 값이 false이면 순회를 계속하고 true이면 순회를 중단한다.
이터러블과 유사 배열 객체
- 유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말한다.
- length 프로퍼티를 갖기 때문에 for 문으로 순회할수 있고, 인덱스로 프로퍼티 값에 접근할 수 있다.
- 유사 배열 객체는 Symbol.lterator 메서드가 없기 때문에 이터러블이 아니라 일반 객체다.
- 단, arguments, NodeList, HTMLCollection은 유사 배열 객체이면서 이터러블이다.
이터레이션 프로토콜의 필요성
- ES6 이전의 순회 가능한 데이터 컬렉션 등은 통일된 규약 없이 각자 나름의 구조를 가지고 다양한 방법으로 순회할 수 있었다.
- ES6에서는 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 for … of 문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화하였다.
- 이터러블은 이러한 데이터 소비자(ex - for … of문)에 의해 사용되므로 데이터 공급자의 역할을 한다고 할 수 있다.
- 데이터 공급자가 이터레이션 프로토콜을 준수하도록 규정하면 데이터 소비자는 이터레이션 프로토콜만 지원하도록 구현하면 된다. -> 이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여 데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록 데이터 소비자와 데이터 공급자를 연결하는 인터페이스의 역할을 한다.
사용자 정의 이터러블
이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면 사용자 정의 이터러블이 된다.
// 피보나치 수열을 구현한 사용자 정의 이터러블
const fibonacci = {
// Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수한다.
[Symbol.iterator]() {
let [pre, cur] = [0, 1];
const max = 10; // 수열의 최대값
// Symbol.iterator 메서드는 next 메서드를 소유한 이터레이터를 반환해야 하고
// next 메서드는 이터레이터 리절트 객체를 반환해야 한다.
return {
next() {
[pre, cur] = [cur, pre + cur];
// 이터레이터 리절트 객체를 반환한다.
return { value: cur, done: cur >= max };
},
};
},
};
// 이터러블인 fibonacci 객체를 순회할 때마다 next 메서드가 호출된다.
for (const num of fibonacci) {
console.log(num); // 1 2 3 5 8
}
- 사용자 정의 이터러블은 이터레이션 프로토콜을 준수하도록 Symbol.iterator 메서드를 구현하고 next 메서드를 갖는 이터레이터를 반환하도록 한다.
- 이터레이터의 next 메서드는 이터레이터 리절트 객체를 반환한다.
- 이터러블이면서 이터레이터인 객체를 생성하면 Symbol.iterator 메서드를 호출하지 않아도 된다.
const fibonacci = function (max) {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() {
return this;
},
next() {
[pre, cur] = [cur, pre + cur];
return { value: cur, done: cur >= max };
},
};
};
- done 프로퍼티를 생략하면 무한 이터러블을 생성하는 함수를 구현할 수 있다.
- 무한 이터러블은 지연 평가를 통해 데이터를 생성한다.
- 지연 평가는 데이터가 필요한 시점 이전까지는 미리 데이터를 생성하지 않다가 데이터가 필요한 시점이 되면 그때야 비로소 데이터를 생성하는 기법이다.
- 예를 들어 for … of 문의 경우 이터러블을 순회할 때 이터레이터의 next 메서드를 호출하는데 이때 데이터가 생성된다.
- 지연 평가를 사용하면 불필요한 데이터를 미리 생성하지 않고 필요한 데이터를 필요한 순간에 생성하므로 빠른 실행 속도를 기대할 수 있고 불필요한 메모리를 소비하지 않는다는 장점이 있다.
출처
모던 자바스크립트 Deep Dive
1003
35장 스프레드 문법
- 스프레드 문법은 하나로 뭉쳐 있는 여러 값들의 집합을 펼쳐서 개별적인 값들의 목록으로 만든다.
- 스프레드 문법을 사용할 수 있는 대상은 이터러블에 한정된다.
- 스프레드 문법의 결과는 값이 아니라 값들의 목록이다. -> … 이 피연산자를 연산하여 값을 생성하는 연산자가 아님을 의미하고, 따라서 스프레드 문법의 결과는 변수에 할당할 수 없다.
- 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용할 수 있다.
- 함수 호출문의 인수 목록
- 배열 리터럴의 요소 목록
- 객체 리터럴의 프로퍼티 목록
함수 호출문의 인수 목록에서 사용하는 경우
- Math.max 메서드는 매개변수 개수를 확정할 수 없는 가변 인자 함수다. 여러 개의 숫자를 인수로 전달받아 인수 중에서 최대값을 반환한다.
- 배열을 인수로 전달하면 최대값을 구할 수 없으므로 NaN을 반환한다.
- 이 문제를 해결하기 위해서는 스프레드 문법을 사용한다.
cosnt arr = [1, 2, 3];
const max = Math.max(...arr);
- 스프레드 문법은 Rest 파라미터와 형태가 동일하여 혼동할 수 있다.
- Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받기 위해 매개변수 이름 앞에 … 을 붙이는 것이다.
- 스프레드 문법은 여러 값이 하나로 뭉쳐 있는 배열과 같은 이터러블을 펼쳐서 개별적인 값들의 목록을 만드는 것이다.
- 따라서 Rest 파라미터와 스프레드 문법은 서로 반대의 개념이다.
배열 리터럴 내부에서 사용하는 경우
concat
- ES5에서 2개의 배열을 1개의 배열로 결합하고 싶은 경우 배열 리터럴만으로 해결할 수 없고 concat 메서드를 사용해야 했다.
- 스프레드 문법을 사용하면 별도의 메서드를 사용하지 않고 배열 리터럴만으로 2개의 배열을 결합할 수 있다.
const arr = [...[1, 2], ...[3, 4]];
splice
- 배열의 중간에 다른 배열의 요소들을 추가하거나 제거하려면 splice 메서드를 사용한다.
- 이때 세 번째 인수로 배열을 전달하면 배열 자체가 추가된다.
- 배열을 목록으로 해체하여 전달해야 하는데, 스프레드 문법을 사용하면 간결하고 가독성 좋게 표현할 수 있다.
const arr1 = [1, 4];
const arr2 = [2, 3];
arr1.splice(1, 0, ...arr2);
배열 복사
ES5에서 배열을 복사하려면 slice 메서드를 사용했으나, 스프레드 문법을 사용하면 간결하고 가독성 좋게 표현할 수 있다.
const origin = [1, 2];
const copy = [...origin];
- 원본 배열의 각 요소를 얕은 복사하여 새로운 복사본을 생성한다.
이터러블을 배열로 변환
- 이터러블이면서 유사 배열 객체인 arguments를 배열로 변환하기 위해 스프레드 문법을 사용할 수 있다.
- 위의 경우 더 나은 방법은 Rest 파라미터를 사용하는 것이다.
- 이터러블이 아닌 유사 배열 객체는 스프레드 문법의 대상이 될 수 없다.
- 이터러블이 아닌 유사 배열 객체를 배열로 변경하려면 Array.from 메서드를 사용한다.
객체 리터럴 내부에서 사용하는 경우
- Rest 프로퍼티와 함께 제안되어 있는 스프레드 프로퍼티를 사용하면 객체 리터럴의 프로퍼티 목록에서도 스프레드 문법을 사용할 수 있다.
- 스프레드 문법의 대상은 이터러블이어야 하지만 스프레드 프로퍼티 제안은 일반 객체를 대상으로도 스프레드 문법의 사용을 허용한다.
// 스프레드 프로퍼티
// 객체 복사(얕은 복사)
const obj = { x: 1, y: 2 };
const copy = { ...obj };
console.log(copy); // { x: 1, y: 2 }
console.log(obj === copy); // false
// 객체 병합. 프로퍼티가 중복되는 경우 뒤에 위치한 프로퍼티가 우선권을 갖는다.
const merged = { ...{ x: 1, y: 2 }, ...{ y: 10, z: 3 } };
console.log(merged); // { x: 1, y: 10, z: 3 }
// 특정 프로퍼티 변경
const changed = { ...{ x: 1, y: 2 }, y: 100 };
// changed = { ...{ x: 1, y: 2 }, ...{ y: 100 } }
console.log(changed); // { x: 1, y: 100 }
// 프로퍼티 추가
const added = { ...{ x: 1, y: 2 }, z: 0 };
// added = { ...{ x: 1, y: 2 }, ...{ z: 0 } }
console.log(added); // { x: 1, y: 2, z: 0 }
- 스프레드 프로퍼티는 Object.assign 메서드를 대체할 수 있는 간편한 문법이다.
출처
모던 자바스크립트 Deep Dive