일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 날씨 api
- 탐욕알고리즘
- 배열 중복 제거
- 그리디
- 항해99추천
- NextJS v13
- 중복카테고리
- 클라이언트 컴포넌트
- 자바스크립트
- greedy
- 실전프로젝트
- 카테고리필터
- 항해99솔직후기
- 중복선택
- JavaScript
- 서버 컴포넌트
- db수정
- 숫자를 별점으로
- 로딩 후 실행
- 항해99
- 동전 0
- 항해99후기
- 백준
- 부트캠프항해
- 배열 메소드
- 알고리즘
- react
- server component
- 프로그래머스
- jQuery
- Today
- Total
공부 및 일상기록
[Javascript] 불변성을 유지하는 방법 본문
사실 블로그에서 몇번 다룬 내용이지만 다시 한번 다뤄보려고 한다.
불변성이란 변하지 않는 성질을 의미한다.
우리가 변수 a에 값을 할당하는 것을 이미지로 살펴보자
let a = 'abc'
a = 'bbb'
식별자 a는 메모리에 값을 바로 할당하는 것이 아닌 abc라는 데이터가 존재하는 주소를 값으로 가지고 있다.
여기서 a='bbb'로 재할당하면 어떻게 변하게 될까?
a의 값을 변경하면 새로운 값 bbb가 존재하는 주소값이 변경된다.
이처럼 자바스크립트의 원시데이터들은 한번 만든 값을 바꿀 수 없는 불변성을 가지고 있다.
하지만 참조형은 불변성이 아닌 가변성을 갖는다.
let obj = {
a:1,
b:'abc'
};
위처럼 obj객체를 하나 생성했다. 그럼 메모리는 다음과 같은 구조를 가질 것이다.
먼저 obj식별자에는 b3030이라는 주소값이 할당되어 있고, b3030의 데이터에는 c1010~c2020의 주소값이 할당되어있다.
c1010과 c2020에는 obj내부 데이터가 각각 할당되어있으며 이 역시 데이터의 주소값을 가지고 있다.
c1010과 c2020에 있는 주소값을 따라가 보면 해당 데이터를 찾을 수 있다.
만약 여기서 obj.a = 3 으로 재할당을 하면 어떻게 될까?
그렇다면 아마도 주소 b5050을 만들고 값 3을 할당하고, c1010에서 가지고있는 주소값을 b5050으로 바꾸게 될것이다.
그럼 실제 obj의 메모리값은 b3030으로 변한게 없지만 데이터는 변하게 된것이다.
그렇다면 우리가 불변 객체를 만들어 주려면 어떻게 해야할까?
객체에 재할당이나 복사를 해야할 때 깊은 복사를 통해 값을 복사하면 된다.
깊은 복사란 객체안에 객체가 있는 경우에도 원본과의 참조가 완전히 끊어진 객체를 생성하는 복사를 의미한다.
1. 재귀함수를 구현하여 복사한다.
let 학생 = {
이름: "휘린",
반: 3,
성별: "남자",
친구: {
이름: "피카츄",
},
};
let copyObjectDeep = function (target) {
let result = {};
if (typeof target === "object" && target !== null) {
for (let prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
};
let 학생2 = copyObjectDeep(학생);
학생2.이름 = "민수";
학생2.친구.이름 = "라이츄";
console.log(학생 === 학생2); //false
console.log(학생.이름, 학생2.이름); //휘린 민수
console.log(학생.친구.이름, 학생2.친구.이름); //피카츄 라이츄
위 함수는 재귀복사를 통한 깊은 복사를 하는 간단한 예시이다. 설명해보자면, copyObjectDeep 함수는 복사하려는 대상이 객체이면 해당 객체를 돌면서 각 요소를 다시한번 copyObjectDeep에 넣어 내부에 모든 객체를 검사하여 복사 하도록 한다. result에 객체 리터럴로 새로운 객체를 만들고 해당 객체에 반환값을 넣으므로 완전히 새로운 객체를 만들게 되는 것이다.
2. Spread연산자 ( ... )를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = { ...obj };
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
위처럼 스프레드 연산자를 통해 새로운 객체 안에 obj1의 속성을 복사하여 obj2를 만들면 다른 주소를 갖게된다.
하지만 이는 딱 1depth까지만 깊은 복사가 이뤄지고 객체안의 객체가 존재했다면 그 객체안의 객체는 얕은 복사가 이뤄지게 된다.
3. Object.assign() 메소드를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
Object.assign() 메소드를 통해 첫 번째 인자로 빈 객체를, 두 번째 인자로 obj1을 넣어서 obj2에 할당하면 새로운 객체가 만들어진다.
하지만 이 역시 딱 1depth까지만 이뤄지게 된다.
'개발 > Javascript' 카테고리의 다른 글
[Javascript] map, forEach, reduce에 대하여 (0) | 2023.01.16 |
---|---|
[Javascript] 자바스크립트에서 데이터 형변환 (0) | 2023.01.16 |
[Javascript] 프로토타입이란 무엇인가? (0) | 2023.01.16 |
[Javascript] AJAX 란? (0) | 2023.01.16 |
[Javascript] this (0) | 2023.01.16 |