-
📌 원시 데이터 : 변경이 불가능한 값
String, Number, Boolean, undefined, null
메모리 영역에서의 변경은 불가능하며, 새로운 값을 만들때 메모리에 같은 값이 있으면 이미 만들어진 메모리 주소의 값을 바라보지만, 새로운 값일 경우 새로운 메모리에 할당한다.
let str = 'Hello'; str = 'world';
첫번째 구문이 실행되면 메모리에 문자열 'Hello' 가 생성되고, 변수 str은 'Hello'의 메모리 주소를 가리킨다.
두번째 구문이 실행되면 이전에 생성된 'Hello'를 수정하는 것이 아니라 새로운 메모리에 새로운 문자열 'World'를 생성하고 변수 str은 이를 가리킨다. 따라서 메모리에는 'Hello'와 'World' 모두 존재하고 있으며, 변수 str은 처음에 'Hello'를 가리키고 있다가 'World'를 가리키도록 변경된 것이다.
let statement = 'I am an immutable value'; // string은 immutable value let otherStr = statement.slice(8, 17); console.log(otherStr); // 'immutable' console.log(statement); // 'I am an immutable value'
두번째 구문의 .slice( )메서드는 변수 statement 에 저장된 문자열을 변경하는 것이 아니라, 새로운 문자열을 생성하여 반환한다.
📌참조형 데이터 : 변경이 가능한 값
Object, Array, Function
메모리상에서 변경이 가능하며, 새로운 값을 만들 때마다 새로운 메모리 주소에 할당된다.(같은 값이어도 새로운 메모리에 할당한다.)
let a = {k: 1} let b = {k: 1} console.log(a, b, a===b); // {k: 1} {k: 1} false
언뜻 모양만 보면 같은 값으로 보이지만 다른 메모리 주소에 할당이 되므로 일치 연산자로 비교하면 false값이 출력된다.
let a = {k: 1} let b = {k: 1} a.k = 7; b = a; console.log(a, b, a===b); // {k: 7} {k: 7} true a,k = 2; console.log(a, b, a===b); // {k: 2} {k: 2} true
a, b가 서로 같은 메모리 주소의 객체를 바라보게 되었으므로 a와 b는 서로 같은 값을 공유하게 되고, 한쪽에서 해당 값을 수정해도 같은 메모리를 바라보고 있으므로 다른 쪽에서도 변경된 값을 참조하게 된다.
이러한 현상이 의도된 경우라면 문제가 없지만, 의도하지 않은 부분이라면 문제가 될 수 있다. 그래서 이런 문제를 해결하기 위해서는 '복사'라는 개념을 이해하고 사용하여야 한다.
📌얕은 복사와 깊은 복사
얕은 복사는 겉표면만 복사하는 개념이고, 깊은 복사는 그 안의 데이터 모두 복사하는 개념이다.
Object.assign( )
Object.assign()은 타겟 객체로 출처 객체의 프로퍼티를 복사한다. 이때, 출처 객체의 프로퍼티와 동일한 프로퍼티를 가진 타겟의 프로퍼티는 출처 객체의 프로퍼티로 덮어쓰기 된다.
const user = { nmae: 'eunhye', age: 29, email: ['eunhye919@gmail.com'] } const copyUser = Object.assign({}, user); // Object.assign(타켓/대상객체, 출처객체); console.log(copyUser === user) // false user.age = 30; console.log(user.age); // 30 console.log(copyUser.age) // 29
전개연산자
const user = { nmae: 'eunhye', age: 29, email: ['eunhye919@gmail.com'] } const copyUser = {...user} console.log(copyUser === user) // false user.age = 30; console.log(user.age); // 30 console.log(copyUser.age) // 29
위의 내용들은 모두 얕은 복사에 해당한다. 얕은 복사는 원시데이터만 복사되고 그 안의 배열이나 객체와 같은 참조형 데이터는 여전히 같은 메모리를 바라보는 것이다.
const user = { nmae: 'eunhye', age: 29, email: ['eunhye919@gmail.com'] } const copyUser = {...user} user.email.push('masimel@naver.com'); console.log(user.email === copyUser.email); // true
lodash package 사용
lodash package에서 제공하는 .cloneDeep( ) 메서드를 사용하여 깊은 복사를 할 수 있다.
const user = { nmae: 'eunhye', age: 29, email: ['eunhye919@gmail.com'] } const copyUser = _.cloneDeep(user); user.email.push('masimel@naver.com'); console.log(user.email === copyUser.email); // false
참고 사이트
https://poiemaweb.com/js-immutability
https://www.geeksforgeeks.org/lodash-_-clonedeep-method/
728x90'Javascript' 카테고리의 다른 글
reduce 활용하기 (0) 2022.11.17 this (2) 2022.09.10 JS 프로처럼 쓰는 팁 (0) 2022.09.05 데이터 불변성 (0) 2022.09.02 DOMContentLoaded VS load (0) 2022.09.02 댓글