JavaScript

[Javascript] 참조, 얕은복사, 깊은복사

prefer2 2021. 8. 24. 13:47

 

객체와 원시 타입의 근본적인 차이 중 하나는 객체는 ‘참조에 의해(by reference)’ 저장되고 복사된다는 것. 반면 원시값(문자열, 숫자, 불린 값)은 ‘값 그대로’ 저장·할당되고 복사된다.

객체를 사용할 때 주의해야할 참조, 얕은복사, 깊은복사에 대해 정리해 보려 합니다.

 

참조


var array = ['a', 'b', 'c'];
var ref = array;
ref[0] = 'd';
console.log(array); // ['d', 'b', 'c']

객체는 다른 변수에 대입할 때 값을 복사하는 게 아니라 참조(메모리의 주소)를 복사한다.

let a = {};
let b = a; // 참조에 의한 복사

console.log( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
console.log( a === b ); // true

/*-------------------*/
let c = {};
let d = {}; // 독립된 두 객체

console.log( c == d ); // false
console.log( c === d); //false

참조에 의한 복사는 같은 값을 참조하고 있기 때문에 동등하다. 반면, 독립된 두 객체는 눈으로 보기에는 동일하지만 서로 다른 객체이기 때문에 일치, 동등하지 않다.

 

얕은복사


가장 상위 객체만 새로 생성되고 내부 객체들은 참조 관계인 경우

원래값과 복사된 값이 같은 참조를 가리키고있는 것을 말한다. 객체안에 객체가 있을 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은 복사라고 한다.

assign

const obj = {
  a: 1,
  b: {
    c: 2,
  },
};

const copiedObj = Object.assign({}, obj);

copiedObj.b.c = 3

obj === copiedObj // false
obj.b.c === copiedObj.b.c // true

Object.assign() 메소드는목표 객체에 동일한 키를 갖는 속성이 존재할 경우 그 속성 값은 출처 객체의 속성 값으로 덮어쓴다.

spread

const original = {
  a: 1,
  b: 2,
  c: {
    d: 3,
  },
}

const copied = { ...original }

original.a = 1000
original.c.d = 3000

console.log(copied.a) // 1
console.log(copied.c.d) // 3000

ES6의 전개연산자(spread)는 얕은 복사를 해준다

 

깊은복사


내부 객체까지 모두 새로 생성된 것. 원본과의 참조가 완전히 끊어진 객체를 말한다

JSON

const cloneObj = obj => JSON.parse(JSON.stringify(obj))

const original = {
  a: 1,
  b: {
    c: 2,
  },
}

const copied = cloneObj(original)

original.a = 1000
original.b.c = 2000

console.log(copied.a) // 1
console.log(copied.b.c) // 2

JSON.parse(JSON.stringify(객체))를 사용해도 크게 문제는 없으나, Math, Date 같은 객체를 복사할 수 없다는 단점이 있다. 따라서 실무에서는 lodash 같은 라이브러리를 사용하곤 한다.

 

참조

(JavaScript) 객체의 복사

참조에 의한 객체 복사

[Javascript] 얕은 복사, 깊은 복사

반응형