[TIL] [JavaScript] 자바스크립트의 불변성(Immutability)
불변성(Immutability)
- 데이터의 원본이 훼손되는 것을 막는 것
데이터 타입에 따른 복사
- 자바스크립트의 데이터타입에는 크게 기본형과 참조형이 있는데, 기본적으로 기본형은 불변값이고 참조형은 가변값이다.
1) 기본형(원시형) : 불변값
- 위 그림에서 변수 p1와 변수p2는 데이터 영역의 같은 주소값인 1을 참조하고 있다.
p1 === p2 // true
- 변수 p3은 p1의 값을 복사했다
- 변수 p3의 값이 2로 바뀌었는데, 기존 데이터 1의 값이 변한 것이 아니라 새로운 데이터를 만들어 새로운 주소값을 참조한다.
2) 참조형 : 가변값
- 위 그림에서 변수 o1와 변수o2는 프로퍼티와 값이 동일한 객체의 값이 할당되었지만, 참조하는 주소값은 다르다.
o1 === o2 // false
- 변수 o3은 o1의 값을 복사했다
- 변수 o3의 프로퍼티 name의 값이 "kim"에서 "lee"로 변경되었는데, 기존값인 o1의 값도 변하게 되었다.
불변성을 유지한 참조형 데이터의 복사
1) Object.assign()
let user = {
name:"name",
urls:{
portfolio:"github link"
}
}
let hannah = Object.assign({},user)
hannah.name = "hannah"
console.log("user", user)
console.log("hannah", hannah)
2) 전개 구문(spread operator)
let user = {
name:"name",
urls:{
portfolio:"github link"
}
}
let hannah = {...user}
hannah.name = "hannah"
console.log("user", user)
console.log("hannah", hannah)
- 복사한 객체의 프로퍼티 name의 값을 변경했지만, 기존 user 객체의 데이터는 그대로 유지
✨ 중첩된 참조형 객체 복사
- 중첩된 참조형 객체를 복사하기 위해서는 깊은 복사를 해야한다.
- 깊은 복사는 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법이다.
1) Object.assign() etc..
- 복사하려는 객체의 프로퍼티를
Object.assign()
로 복사해서 불변성을 유지할 수 있다. - 단점은 중첩된 객체가 이중, 삼중이고 여러 프로퍼티가 객체로 중첩되어 있다면 번거롭다.
let user = {
name:"name",
urls:{
portfolio:"github link"
}
}
let hannah = Object.assign({},user)
hannah.urls = Object.assign({},user.urls)
hannah.name = "hannah"
hannah.urls.portfolio = "velog link"
console.log("user", user)
console.log("hannah", hannah)
- 예를 들어, 아래와 같이 urls의 portfolio의 값이 배열이고, 복사한 객체가 배열에 값을 push 메서드로 추가한다면...
let user = {
name:"name",
urls:{
portfolio:["github","velog"]
}
}
let hannah = Object.assign({},user)
hannah.urls = Object.assign({},user.urls)
hannah.name = "hannah"
hannah.urls.portfolio.push("google")
console.log("user", user)
console.log("hannah", hannah)
- 기존 객체의 값 배열에도 google이 추가되었다.
- 이 경우에는
push()
메서드가 아닌concat()
메서드로 새로운 배열을 반환하면 문제를 해결할 수 있다.
hannah.urls.portfolio = hannah.urls.portfolio.concat("google")
2) JSON.parse() & JSON.stringify()
let user = {
name:"name",
urls:{
portfolio:["github","velog"]
}
}
const copyObjViaJSON = (targetObj) => {
return JSON.parse(JSON.stringify(targetObj))
}
let hannah = copyObjViaJSON(user)
hannah.name = "hannah"
hannah.urls.portfolio.push("google")
console.log("user", user)
console.log("hannah", hannah)
- JSON 문법으로 문자열로 전환했다가 다시 JSON 객체로 바꾸는 방법
- 단순하고 잘 동작되지만, 메서드(함수)나 숨겨진 프로퍼티은
__proto__
나 getter/setter 등과 같이 JSON으로 변경할 수 없는 프로퍼티들은 모두 무시하는 단점이 있다.
3) 재귀함수
- 재귀: 자신을 정의할 때 자기 자신을 재참조하는 방법.
const deepCopyFunction = (inObject) => {
let outObject, value, key
if (typeof inObject !== "object" || inObject === null) {
return inObject // Return the value if inObject is not an object
}
// Create an array or object to hold the values
outObject = Array.isArray(inObject) ? [] : {}
for (key in inObject) {
value = inObject[key]
// Recursively (deep) copy for nested objects, including arrays
outObject[key] = deepCopyFunction(value)
}
return outObject
}
출처:
생활코딩 - JavaScript Immutability
코어자바스크립트 - 정재남
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
https://ko.wikipedia.org/wiki/%EC%9E%AC%EA%B7%80_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)
https://javascript.plainenglish.io/how-to-deep-copy-objects-and-arrays-in-javascript-7c911359b089
Author And Source
이 문제에 관하여([TIL] [JavaScript] 자바스크립트의 불변성(Immutability)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@dev-hannahk/til-js-immutability저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)