자바스크립트 shallow & deep copy

CodeLog·2021년 1월 9일
0

알고갑시다!

참조타입의 자료는 = 연산자로 할당하면 주소를 복사한다.

object라는 객체를 생성하고 이 객체를 newObject로 할당했습니다. 단순히 생각하면 똑같은 객체 두개가 생성되어 newObject.name을 변경했을때 object 와 newObjects는 서로다른 객체라고 판단 되지만 결과 값은 완전히 똑같은 상태입니다.
여기서 복사란 object가 메모리에서 가지고 있는 것은 객체 자체의 값이 아닌 heap 메모리에 저장된 객체의 "주소값"입니다.
따라서 주소값이 복사되는것이지 새로운 객체를 생성한 것이 아닙니다.

let object = { name : '홍길동' , age : 19 }
let newObject = object;
newObject.name = '영구'

console.log(object) //{"name":"영구","age":19}
console.log(newObject)//{"name":"영구","age":19}

❗️메모리 구조와 같이 생각하기

메모리구조의 정확한 설명 보다는 간편하게 작성하면서 요점만 파악해보겠습니다.

  1. object 변수가 선언되면 Stack에 쌓인다
  2. Heap 메모리에 객체(데이터)를 생성한다.
    -생성과 함께 object의 변수에 "2ad213ca"라는 Heap에 저장된 객체(데이터)의 주소를 참조한다.
  3. newObject 변수가 선언되면 Stack에 쌓는다
    🔑여기서 중요합니다.
    - newObject = object 이렇게 할당을 하게 되면 object의 주소값을 newObject에 할당하게 됩니다.
    따라서 아래 그림과 같이 두개의 서로다른 변수는 동일한 객체(데이터)를 참조하게됩니다.

shallow copy

복사하려는 객체의 값이 참조타입이 아닌경우에만 1 depth만 복사를 한다.
(원시타입 : int, string, boolean, null, undefined)
(참조타입 : 함수 ,배열, 객체)

Object.assign()

이 함수는 첫번째인자 복사가 저장될 변수, 두번째 파라미터 복사할 객체.
값을 객체로 가지는 속성이 있을경우 해당 부분까지 완벽하게 복사를 할 수없는 부분이 특징이다.

  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}

  obj1.a = 1;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}

  obj2.a = 2;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}

  obj2.b.c = 3; // obj1, obj2 모두에 영향을 줌
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}

spread syntax

전개구문이라하고 이 sytnax또한 Object.assign() 처럼 동일하게 동작한다.
깊이 레벨이 1깊이에서 효과적이다

deep copy

복사하려는 객체 내 값이 객체라도 완전히 복사를 할수있는것이다.
값이 참초타입이여도 메모리공간을 새로 만들어 데이터를 저장하게 된다.

재귀함수

재귀를 통해서 객체를 복사하는 방법입니다.
복사하려는 객체 값이 객체일 경우 재귀를 실행하여 모든 값을 깊은복사하는 형태입니다.

let object = {
  name : '김코딩',
  age : 19,
  skillStack : {
    web : {
      backEnd : ' node.js',
      forontEnd : 'HTML, CSS , React',
    }
  }
}
function cloneObject(obj) {
  var clone = {};
  for (var key in obj) {
    if (typeof obj[key] == "object" && obj[key] != null) {
      clone[key] = cloneObject(obj[key]);
    } else {
      clone[key] = obj[key];
    }
  }
  return clone;
}
let newObject = cloneObject(object)

console.log(newObject)
object.skillStack.web.backEnd = 'PHP'
newObject.skillStack.web.backEnd = 'python'

console.log(object.skillStack.web.backEnd) //PHP
console.log(newObject.skillStack.web.backEnd)//python

JSON.stringify()

자바스크립트 object를 스트링 포멧으로 변환하고 다시 object로 변환하는 과정에서
완전히 새로운 객체를 생성하는 특징을 이용한 것입니다.
가장 간단한 방법이지만, 함수, Date 객체, 정규표현식, infitity등의 데이터는 복사되지 않고 유실된다.
recrsion , lodash 보다 성능면에서 떨어진다.

obj1 = { a: 0 , b: { c: 0}};
  let obj3 = JSON.parse(JSON.stringify(obj1));
  obj1.a = 4;
  obj1.b.c = 4;
  console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
profile
개발로그

0개의 댓글