Skip to content

Latest commit

 

History

History
140 lines (112 loc) · 4.13 KB

이소민.md

File metadata and controls

140 lines (112 loc) · 4.13 KB

1. Shallow Copy & Deep Copy

1-0. 참조 타입부터 알아보자.

  • 참조 타입

    • 변수에 실제 값을 저장하지 않고 실제 값이 저장된 메모리 주소를 참조
    • 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사됨.
    • 객체, 배열, 함수, 날짜
  • 원시 타입

    • 변수에 값 자체 저장
    • 숫자, 문자열, 불리언, null, undefined

1-1. 얕은 복사

  • 원시 타입 값들을 가진 일반 객체를 얕은 복사할 경우
    객체 내의 원시 타입 값들은 값 복사가 되고, 서로 다른 메모리 주소를 가르키기 때문에 문제되지 않음.

  • 중첩 객체를 얕은 복사할 경우
    내부 객체를 복사할 때 참조 값을 복사하기 때문에 원본 객체와 복사 객체가 같은 참조를 가지게 되고
    객체 속성 값을 변경할 경우 해당 값을 참조하는 다른 객체에도 영향을 미치게 되는 문제 발생.

    → 즉, 참조 타입의 경우 값이 객체의 주소를 참조하고 있기 때문에
    얕은 복사를 수행하면 주소 값만 복사되어 원본 객체와 복사 객체가 같은 객체를 참조하는 문제 발생.


1-2. 깊은 복사

  • 깊은 복사는 객체에 중첩되어 있는 객체까지 모두 실제 값을 복사해 원시 값처럼 완전한 복사본을 만듦

  • 별개의 메모리 주소를 참조하기 때문에 서로 독립적인 객체임

    → 원본을 보존할 필요가 있을 경우 깊은 복사를 사용하는 것이 좋음



2. 예제로 이해하기

2-1. 얕은 복사 방법

2-1-1. spread 연산자

let obj = { a: 1, b: 2, c: 3 };
let clone = { ...obj }

2-1-2. Object.assign()

let obj = { a: 1, b: 2, c: 3 };
let clone = Object.assign({}, obj);

2-1-3. slice()

let arr = [1,2,3];
let clone = arr.slice();

2-1-4.concat()

let arr = [1,2,3];
let clone = [].concat(arr);

* 얕은 복사의 경우 중첩 객체를 처리하지 못함

let user = {
  name: "John",
  sizes: {
    height: 182,
    weight: 50
  }
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true

user.sizes.width = 79; 
alert(clone.sizes.width); // 79

2-2. 깊은 복사 방법

2-2-1. spread 연산자

let clone = {...user, sizes: {...user.sizes}};

2-2-2. Object.assign()

let clone = Object.assign({}, user, {sizes: Object.assign({}, user.sizes)});
  • 위 두가지 방법은 복사해야하는 속성을 하나씩 지정해야 하므로 불편할 수 있음.

2-2-3. JSON.parse && JSON.stringify

let clone = JSON.parse(JSON.stringify(user));
  • 객체가 JSON으로 직렬화(serialization)되어 문자열로 변환되기 때문에, 함수나 심볼같은 특별한 타입의 속성은 포함되지 않음.
  • 객체의 속성 값 중에 순환 참조(circular reference)가 있는 경우 동작하지 않음.
  • 객체의 크기가 크다면 JSON 문자열을 만들기 위해 메모리를 많이 사용할 수 있음.

2-2-4. 재귀함수, 반복문 사용

// Object.assign()과 재귀함수 이용하여 중첩 객체 값 복사하기
function deepCopyWithAssign(obj) {
    let newObj = Object.assign({}, obj);
    for (let key in newObj) {
        if (typeof newObj[key] === 'object' && newObj[key] !== null) {
        newObj[key] = deepCopyWithAssign(newObj[key]);
        }
    }
    return newObj;
}

let clone = deepCopyWithAssign(user);


// 재귀함수 이용하여 중첩 객체 값 복사하기 
function deepCopy(obj) {
  let result = {};
  for (let key in obj) {
    if (typeof obj[key] === "object" && obj[key] !== null) {
      result[key] = deepCopy(obj[key]); // 객체면 재귀적으로 복사
    } else {
      result[key] = obj[key]; // 객체 아니면 값 복사 
    }
  }
  return result;
}

let clone2 = deepCopy(user);

// null도 객체 타입으로 인식하기 때문에 obj[key] !== null 추가

[ 참고 자료 ]

모던 자바스크립트 튜토리얼
자바스크립트 딥다이브