참조 타입과 참조 복사
객체·배열·함수를 담은 변수에는 값이 아니라 객체의 참조가 저장된다. 대입하면 참조가 복사되므로 두 변수가 같은 객체를 가리킨다.
Seobway · · 7분
문제 상황
원시 타입은 대입할 때 값이 복사되어 두 변수가 서로 영향을 주지 않는다.
객체는 다르게 동작한다.
const original = { name: "서브웨이" };
const copy = original;
copy.name = "바뀜";
console.log(original.name); // "바뀜" (원본도 바뀐다)
copy = original 에서 복사되는 것은 객체가 아니라 객체의 참조다. 두 변수가 같은 객체를 가리키므로
한쪽에서 속성을 바꾸면 다른 쪽에서도 바뀐 값이 보인다.
동작 원리
참조 타입은 변수에 값 대신 참조(reference), 즉 힙에 할당된 객체의 위치 정보가 저장되는 타입이다.
원시 타입 7가지를 제외한 모든 값이 여기에 속한다.
- 객체
{} - 배열
[] - 함수
function () {} - 그 밖에
Date·Map·Set·RegExp등
객체 리터럴을 평가하면 엔진은 힙에 객체를 할당하고, 변수에는 그 객체의 참조를 저장한다.
대입(=)과 인자 전달은 이 참조를 복사하므로, 같은 참조를 가진 변수들은 모두 같은 객체를 가리킨다.
인터랙티브 다이어그램: 대입 시 참조가 복사되는 과정 (단계별로 재생할 수 있다)
- const original = { name: "서브웨이" } 를 평가하면 힙에 객체가 할당된다.
- original 에는 객체의 참조가 저장된다.
- const copy = original 은 참조를 복사한다. 객체는 새로 만들어지지 않는다.
- copy.name 을 수정하면 참조를 따라가 힙의 객체를 직접 수정한다.
- original 도 같은 객체를 참조하므로 수정된 값이 읽힌다.
동등 비교
참조 타입에서 === 는 두 피연산자가 같은 객체를 참조하는지 비교한다. 속성 값이 같은지는 보지 않는다.
{ a: 1 } === { a: 1 } // false (내용은 같지만 서로 다른 객체)
[1, 2] === [1, 2] // false
const x = { a: 1 };
const y = x;
x === y // true (같은 참조)
내용을 비교하려면 속성을 직접 순회해 비교해야 한다. JSON.stringify 결과를 비교하는 방법도 있지만
속성 순서, undefined·함수 값 누락 때문에 정확하지 않다.
예제
참조 복사와 스프레드 복사의 차이를 비교한다.
const original = { name: "서브웨이", tags: ["js"] };
const alias = original; // 참조 복사: 같은 객체
const shallow = { ...original }; // 얕은 복사: 최상위만 새 객체
alias.name = "별칭이 바꿈";
console.log("1:", original.name); // 바뀐다
shallow.name = "복사본이 바꿈";
console.log("2:", original.name); // 바뀌지 않는다
// 중첩된 배열은 여전히 공유된다
shallow.tags.push("ts");
console.log("3:", original.tags); // 같이 바뀐다
console.log("같은 객체?", original === alias, original === shallow);
3번 결과가 달라지는 이유는 { ...original } 이 최상위 속성만 새 객체로 복사하고, 속성 값인 배열은
참조만 복사하기 때문이다. 이 차이는 얕은 복사와 깊은 복사에서 다룬다.
자주 하는 실수
정리
참조 타입(객체·배열·함수)의 변수에는 객체의 참조가 저장된다. 대입과 인자 전달은 참조를 복사하므로
여러 변수가 같은 객체를 가리킬 수 있고, === 는 참조가 같은지를 비교한다.
-
const객체의 속성을 바꿀 수 있는 이유를 설명할 수 있다 -
{a:1} === {a:1}이false인 이유를 안다 - 스프레드로 복사해도 중첩된 값이 공유되는 이유를 안다
참고
- [1] JavaScript data types and data structures — MDN Web Docs
- [2] Object — MDN Web Docs
- [3] The Object Type — ECMAScript 사양
관련 글
- 원시 타입과 값 복사 → (선행 개념)
- 프로토타입과 프로토타입 체인 →
- 얕은 복사와 깊은 복사 → (다음 글)
- javascript
- 타입
- 참조타입
- 객체