솔미는 성장중

[JS] 불변성 본문

JavaScript

[JS] 불변성

solming 2023. 7. 31. 23:52
728x90

원시 데이터의 "데이터 불변성"

원시 데이터 : String, Number, Boolean, null, undefined

 

원시 데이터에서는 단순하게 모양이 다르면 false가 나온다고 생각해도 틀리진 않는다.

하지만 정확히는 '메모리 주소'가 같고 다름에 따라 true/false가 바뀐다.

let a = 1
let b = 4
console.log(a,b,a===b) //1 4 false -> 메모리 주소가 달라서 false
b=a
console.log(a,b,a===b) //1 1 true -> b가 a가 가리키는 메모리주소를 가리키게 됨
a=7
console.log(a,b,a===b) //7 1 false -> 메모리 주소가 달라서 false

 

 

새로운 원시 데이터를 사용했을 때 그 원시 주소가 기존 메모리 상에 들어있을 때 원시 데이터를
새로운 메모리에 만들지 않고, 기존 메모리 주소를 바라보도록 만든다.
즉, 원시 데이터들은 불변한다!

 


참조형 데이터의 "가변성"

참조형 데이터(object, array, function)

 

참조형 데이터는 새로운 값을 만들 때 마다 새로운 메모리 주소에 할당된다.

let a = {k:1}
let b = {k:1}
console.log(a,b,a===b) // {k:1} {k:1} false -> a는 1번메모리, b는 2번메모리
a.k = 7 //1번 메모리 내용 수정
b=a //b가 1번 메모리 주소를 바라보게 됨.
console.log(a,b,a===b) //{k:7} {k:7} true
a.k=2 //1번 메모리 내용 수정
console.log(a,b,a===b) //{k:2} {k:2} true -> b도 함께 바뀐 모습!!!!!!!!!!!!
let c = b //c도 1번 메모리를 바라보게 됨.
console.log(a,b,c, a===c) //{k:2} {k:2} {k:2} true
a.k=10
console.log(a,b,c,a===c) //{k:9} {k:9} {k:9} true

참조형 데이터에서 'a=b와 같은할당' = '같은 메모리 주소를 보게 만든다.'라는 의미이다.'

 

a,b를 별개의 데이터로 관리하고 싶다면 '복사'를 이용해야한다.

 


복사

 

문제 상황 예시) user와 copyUser를 별개의 데이터로 컨트롤하고 싶은데 user를 바꾸는 copyUser도 바뀌는 모습.

const user = {
  name:'solmi',
  age:99,
  emails: [ovo10203@gmail.com]
}
const copyUser = user //여기가 문제!!!!!!!!!!!!!!!!
console.log(copyUser===user) //false

user.age = 20
console.log(user) //~~, age:20, ~~
console.log(copyUser) // ~~, age:20, ~~

해결방법

 얕은 복사 

표면만 복사

1.

Object.assign({},user)

 

2.

Object.assign{...user}

전개연산자를 사용하기 전에 빈 객체가 만들어짐 { }

전개연산자는 중괄호를 날리고, 속성 값을 빈 객체 속에 넣음.

 

cf) 배열데이터에선

const  B = A.concat([])
const  B = [...A]

 

다만, 얕은 복사는 user 객체 데이터 하나만 복사가 됐기에..!

user.emails에서 emails는 참조형 배열 데이터는 복사가 안되어서 아래와 같은 현상이 일어난다. emails 객체 데이터에 관해선 같은 메모리 주소를 바라보고 있기 때문에!

user.emails.push('1234@gmail.com')
console.log(user.emails === copyUser.emails) //true

 

이를 해결하기 위해선

.

.

.

 

 깊은 복사 ! 

내부에 있는 모든 참조관계까지 새로운 메모리로 복사
(즉, 참조형 데이터 안에 참조형 데이터가 있는 경우는 깊은 복사 추천)

 

  • Lodash사용
npm i Lodash
  •  main.js 상단에 import해주기
import _ from 'lodash'
  • const copyUser 선언 수정해주기
const copyUser = _.cloneDeep(user) //깊은 복사

 

cf) 배열데이터에선

import cloneDeep from 'lodash/cloneDeep'

const b = cloneDeep(a)

 

cf) 객체데이터 예시. 메모리에서 흐름 보기

728x90