회고록 블로그
[공부 필기] JavaScript 문법 공부 20일차 (1) 본문
※ 필자는 초초초보자입니다.
※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.
공부하고 있는 자료 : modern JavaScript tutorial
https://ko.javascript.info/object-copy
✅ 참조에 의한 객체 복사
- 보통 복사하려고 할 때
- 원시값(문자열, 숫자 등)은 값 그대로 저장.할당되고 복사되지만 (값 복사)
- 객체는 참조에 의해(by reference) 저장되고 복사된다.
- 코드 예시
» 아래 코드의 변수 user에는 객체의 값이 아니라 객체가 저장된 "메모리 주소"(참조값)이 저장된다.
let user = {
name: "soySauce",
age: 1
};
» 만약 다른 변수에 user 변수의 값을 복사한다고하면 "참조값"이 복사된다.
✅ 참조에 의한 비교
- 동등 연산자(==), 일치 연산자(===)
» 피연산자인 두 객체가 동일한 객체(참조값)인 경우 참 반환
- 비교 연산자(>, < 등)나 원시값과의 비교 시에는 객체가 원시형으로 변환된다.
» obj1 > obj2 , obj == 5 등
» 이런 코드를 사용하는 경우는 매우 드물다고 한다.
✅ 객체 복사, 병합과 Object.assign
- 객체를 복제하고 싶다면?
» 기존 객체와 독립적이지만(객체의 참조값이 다름), 기존 객체와 똑같은 모습으로 만들고 싶을 때
» 방법1. for ... in 연산자를 사용해서 복사
let user = {
name: "soySauce",
age: 1
};
let clone = {};
for (let key in user) {
clone[key] = user[key];
}
...
// 코드출처 : 모던 자바스크립트(https://ko.javascript.info/object-copy)
» 방법2. Object.assign을 사용
원시형을 복제할 때는 값이 복사되지만
객체 안에 있는 객체형을 복제하려고 할 때는 참조값이 복사된다.
(이렇게 참조값을 복사하는 것을 "얕은 복사(shallow copy)"라고 한다.
객체 안에 있는 객체형을 복제한다는 말이 어려운데, 이건 뒤에서 다시 보기로 하자.
Object.assgin(target, [obj1], [obj2], [obj3], ...);
// 첫번째 인수 : 목표로 하는 객체(클론할 객체)
/* 두번째 인수 이후부터 : 복사하고자 하는 객체(기존 객체들)
두번째, 세번째, ..., n번째 객체의 프로퍼티를 첫번째 인수로 복사한다. */
// 반환값 : dest (참조값)
- Object.assign 예시
» 동일한 이름을 가진 프로퍼티가 있는 경우엔 기존 값이 덮어씌워진다.
"use strict";
let user1 = {
name: "soySauce",
age: 1
};
let user2 = {
name: "kim",
age: 2
};
let user3 = {
age: 3
};
let clone = {};
Object.assign(clone, user1, user2, user3);
console.log(clone); // clone 객체는 프로퍼티가 두 개이다. (age: 3과 name: "kim")
- target이 빈 중괄호이면, 빈 배열에 복사된다.
» 예시
let clone2 = Object.assign({}, user1, user2, user3);
- 이렇게 복사하면, 클론한 객체와 기존 객체의 참조값은 다르다.
✅ 복사하려는 기존 객체가 원시값이 아니라면?
어떻게 복사해야할까
- 아래와 같이 객체 안에 객체가 있다면, 이 값을 어떻게 복제해야할까
let user1 = {
name: "soySauce",
age: 1,
school: {
element: "aSchool",
middle: "bSchool",
high: "cSchool"
}
};
» 일단 프로퍼티를 출력하자.
for (let key in user1) {
console.log(`${key} : ${user1[key]}`);
}
for (let key in user1.school) {
console.log(`${key} : ${user1.school[key]}`);
}
- 단순히 Object.assign을 이용해서 user1.school을 변수 clone에 복사하는 것만으로는 부족하다.
» Object.assign은 이 객체 안에 있는 객체를 복사할 때 얕은 복사(참조값을 복사)하기 때문이다.
» 따라서, 같은 객체를 가리키게 될 뿐 "값"이 복사되는게 아니다.
let clone = {};
clone = Object.assign({}, user1);
console.log (clone.school === user1.school); // true (같은 school 객체를 가리키고 있기 때문에)
- 이 문제를 해결하기 위해서는 깊은 복사(deep cloning)를 이용해야한다.
✅ 깊은 복사(deep cloning)
- 다시 예시코드를 가져와보자.
let user1 = {
name: "soySauce",
age: 1,
school: {
element: "aSchool",
middle: "bSchool",
high: "cSchool"
}
};
- 복사하고 싶은 곳은 변수 clone이며,
변수 user1과 동일한 형태(프로퍼티가 원시형 2개, 객체형 1개)로 복제하는게 목표이다. 이때 (독립적인) "값"으로 복사해야한다.
let clone;
- 깊은 복사는 "user1[key]의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조도 복사해주는 반복문을 사용"하는 방식이다.
» 깊은 복사에서 사용되는 표준 알고리즘은 Structured cloning algorithm이다.
» 프로그래머가 직접 깊은 복사 알고리즘을 구현해야한다.
- 사실 프로그래머가 직접 알고리즘을 구현하지 않아도
자바스크립트 라이브러리 lodash의 메서드 "_.cloneDepp(obj)"나 structuredClone() 등을 사용하면
깊은 복사를 할 수 있다.
※ 일단 깊은 복사를 구현해보자
- 자바스크립트 개념을 이해하기 위한 공부니까 깊은 복사를 직접 구현해보자.
- "user1[key]의 각 값을 검사하면서, 그 값이 객체인 경우 객체의 구조를 복사해주는 재귀함수(또는 반복문)를 사용하면 된다고 한다.
function deepCopyObject(obj) {
let clone = {}; // 빈 객체
for (let key in obj) {
if (typeof obj[key] === "object") { // clone[key]가 object(객체이면)
clone[key] = {}; // clone[key] 빈 객체 만들고
for (let key2 in obj[key]) {
clone[key][key2] = obj[key][key2]; // 객체 안에 객체의 프로퍼티 복사
}
}
else { // object가 아니라면
clone[key] = obj[key]; // 원시타입 복사
}
}
return (clone);
}
- 보통 반복문 보다는 편하게 재귀함수를 사용하는 경우가 많은 듯 하다.
» 반복문을 사용하면 객체 안에 [객체 안에 객체 안에 객체 안에 ... 객체]인 경우를 고려해주지 못하기 때문인 듯 하다.
function deepCopyObject(obj) {
let clone = {}; // 빈 객체
for (let key in obj) {
if (typeof obj[key] === "object") { // clone[key]가 object(객체이면)
clone[key] = deepCopyObject(obj[key]); // 재귀함수
}
else { // object가 아니라면
clone[key] = obj[key]; // 원시타입 복사
}
}
return (clone);
}
추가 참고 자료 : https://leonkong.cc/posts/js-deep-copy.html
'2. 프로그래밍 언어 공부 > JavaScript' 카테고리의 다른 글
[공부 필기] JavaScript 문법 공부 21일차 (0) | 2022.05.15 |
---|---|
[공부 필기] JavaScript 문법 공부 20일차 (2) (0) | 2022.05.12 |
[공부 필기] JavaScript 문법 공부 19일차 (0) | 2022.05.11 |
[공부 필기] JavaScript 문법 공부 18일차 (0) | 2022.05.09 |
[공부 필기] JavaScript 문법 공부 17일차 (0) | 2022.05.08 |