javascript - 얕은 복사와 깊은 복사

김동하·2020년 9월 22일
0

javascript

목록 보기
25/58

0 또는 1만 표현할 수 있는 하나의 메모리 조각을 비트(bit)라고 한다. 메모리는 많은 비트로 구성되어 있고 각 비트는 고유한 식별자를 통해 위치를 확인할 수 있다.

효율을 위해 1바이트를 8비트로 지정했다. 모든 데이터는 바이트의 식별자, 메모리 주솟값으로 서로를 구분한다.

변수 선언 원리

let a;

풀어쓰면 이 데이터의 식별자를 a로 한다 라는 뜻이다. 즉, 변수란 변경 가능한 데이터가 담길 수 있는 공간이다. 임의의 주솟값 1003에 a 라는 이름(식별자)의 데이터를 넣는다. 이후 사용자가 a에 접근하고자 하면 메모리는 a라는 이름을 가진 주소를 검색해 해당 공간에 담긴 데이터를 반환한다.

let a; // 변수 선언
a = "abc" // 변수 a에 데이터 할당

컴퓨터는 실제로 a 라는 이름을 가진 주소를 검색해 그곳에 문자열 "abc"를 저장하지 않는다. 데이터 저장을 위한 별도의 데이터 영역 확보하고 문자열 "abc"를 저장하고 그 주소를 변수 영역에 저장한다. 변수 영역에 1003이라는 주소에 이름이 a이고 값이 주소 5004라는 데이터가 있으고 데이터 영역에서 주소 5004엔 "abc"가 있는 것이다.

이렇게 두 단계로 나눠 저장하는 까닭은 메모리 관리에 효율을 위해서다. 변수 영역과 데이터 영역을 나눠서 처리하는 것이 더 효율적!

만약 "abc"뒤에 "de"를 추가하고 싶다면 데이터 영역에 새로운 주소에 "abcdef"를 추가하고 변수 영역에 원래 존재하던 데이터에 값에 주소를 연결하면 된다. 변수에 할당된 데이터를 변경하면 변수 영역의 주소 1003에 있는 데이터에 연결된 주소만 바꿔주면 된다.

얕은 복사와 깊은 복사

얕은 복사는 바로 아래 단계의 값만 복사하고 깊은 복사는 내부의 모든 값을 하나하나 찾아서 전부 복사하는 방법이다.

const copyObject = function(target){
  let result =[]
  for(let prop in target){
    result[prop] = target[prop]
  }
  return result
}

const user = {
  name:"dongha",
  hobby:{
    one: "1",
    two: "2",
    three : "3"
  }
};

const user2 = copyObject(user)

user2.name = "cat"
console.log(user.name === user2.name) // false

copyObject 함수로 객체 요소를 모두 복제한다. 그리고 user2를 생성하면 user와 다른 객체가 된다.

user.hobby.one = "one"
console.log(user.hobby.one === user2.hobby.one) // true

문제는 중첩된 객체까지 복사되지 않는다는 것이다. 즉, user 객체에 직접 속한 프로퍼티에 대해 완전히 새로운 데이터가 만들어졌지만 hobby 내부의 프로퍼티들은 기존 데이터를 그대로 참조하고 있다. 이러한 상황을 막기 위해 user.hobby 프로퍼티도 불변 객체로 만들어야 한다.

user2.hobby = copyObject(user.hobby)

user.hobby.one = "one"
console.log(user.hobby.one === user2.hobby.one) // false

데이터 복사 과정에서 중첩 객체가 있으면 재귀적으로 복사를 해야 깊은 복사를 할 수 있다.

깊은 복사

const copyObject = function(target) {
    let result = []
    if (typeof target === "object" && target !== null)
        for (let prop in target) {
            result[prop] = copyObject(target[prop])
        } else {
            result = target
        }
    return result
}

target이 객체인 경우(null도 객체라 !==해줌) for in으로 순회하며 재귀적으로 복사하고 target이 객체가 아니면 result를 target 으로 지정해주었다.

JSON을 이용한 깊은 복사

const copyObjectViaJson = function(target){
  return JSON.parse(JSON.stringify(target))
}

user2.name = "cat"
console.log(user.name === user2.name)  // false 

user.hobby.one = "one"
console.log(user.hobby.one === user2.hobby.one)  //false 

객체를 JSON 문법으로 표현된 문자열로 전환했다가 다시 JSON 객체로 바꾸는 방법!

출처 : 코어 자바크스립트

profile
프론트엔드 개발

0개의 댓글