var score = 80;
// 원시 값 80이 복사되어 copy에 할당된다.
var copy = score;
console.log(score); // 80
console.log(copy); // 80
score = 100;
console.log(score); // 100
console.log(copy); // 80
score와 copy의 값은 80으로 동일하지만, 다른 메모리 공간에 저장된 별개의 값이다.
따라서 score의 값을 변경해도 copy에는 영향을 주지 않는다.
사실 변수에는 값이 전달되는 게 아니라 메모리 주소가 전달되므로 "값에 의한 전달"은 정확한 표현이 아니다. 중요한 것은 결국 두 변수의 원시 값은 서로 다른 메모리 공간에 저장되므로 어느 한쪽이 재할당이 되어도 서로 간섭할 수 없다는 것이다.
자바스크립트의 객체는 클래스 없이 생성이 가능하고 이후에 동적으로 프로퍼티와 메소드를 추가할 수 있다. 따라서 원시 값처럼 확보해야할 메모리 공간의 크기를 미리 정해둘 수 없다. 원시 값은 상대적으로 적은 메모리를 소비하지만 객체는 경우에 따라 크기가 매우 클 수도 있다.
이러한 구조적인 단점을 보완하고 메모리 사용의 효율성과 성능을 위해 객체는 변경 가능한 값으로 설계되어 있다. 그러나 원시 값과 달리 여러 개의 식별자가 하나의 객체를 공유할 수 있다는 부작용이 따른다.
얕은 복사와 깊은 복사
- 얕은 복사 : 한 단계까지만 복사 (중첩된 객체는 참조 값을 복사)
- 깊은 복사 : 객체에 중첩되어 있는 객체까지 모두 복사 (원시 값처럼 완전한 복사본 생성)
const o = { x: { y: 1 } }; // 얕은 복사 const c1 = { ...o }; console.log(c1 === o); // false (복사로 생성된 객체는 원본과 다른 객체다.) console.log(c1.x === o.x); // true (참조값이 복사되어 같은 객체를 가리키므로) // lodash 의 cloneDeep 을 사용한 깊은 복사 const _ = require('lodash'); const c2 = _.cloneDeep(o); console.log(c2 === o); // false console.log(c2.x === o.x); // false (중첩 객체가 새로운 메모리 공간에 복사되므로)
var person = {
name: 'Lee'
};
// 참조 값 복사 (얕은 복사)
var copy = person;
person과 copy는 같은 참조 값을 가지므로 같은 객체를 가리키게 된다. 즉, 두 개의 식별자가 하나의 객체를 공유하는 것이다. 따라서 둘 중 한쪽에서 객체를 변경하면 서로 영향을 주고받는다.