자바스크립트는 기본적으로 값에 의한 전달(Pass by Value) 방식을 사용하는 언어입니다. 다만 객체(Object)를 다룰 때는 그 '값'이 곧 참조(reference)라는 점이 중요합니다.
예를 들어, 함수에 숫자(int) 타입의 값을 매개변수로 전달하고 함수 내부에서 그 값을 증가시켜도, 호출자(caller) 쪽의 원래 변수 값은 변경되지 않습니다.
예제 1: 원시 타입(Primitive Type) 전달
let i = 0;
function increment(x) {
x = x + 1
console.log(x)
}
increment(i)
console.log(i)출력 결과
1 0
함수 내부에서는 x가 1로 증가해 1이 출력되지만, 함수 외부의 i는 여전히 0입니다. 이는 함수 호출 시 값이 복사되어 전달되기 때문입니다.
객체 전달 시 동작 방식
객체를 함수에 전달할 때는 두 가지 경우로 나눌 수 있습니다.
- 참조 자체를 재할당하는 경우: 함수 내부에서 매개변수가 새로운 객체를 가리키도록 바꿔도 원본 객체에는 아무런 영향을 주지 않습니다.
- 객체의 내부 상태를 변경(mutate)하는 경우: 매개변수가 참조하는 객체의 속성을 추가하거나 수정하면, 원본 객체에도 그 변경 사항이 그대로 반영됩니다.
예제 2: 객체 참조와 내부 변경
let obj = {'foo': 'bar'};
function updateRef(x) {
// 지역 변수 x의 참조만 변경될 뿐, obj에는 영향이 없음
x = {}
}
function addHelloWorld(y) {
// y가 참조하는 객체에 새로운 속성 추가
y['hello'] = 'world';
}
console.log(obj)
updateRef(obj)
console.log(obj)
addHelloWorld(obj)
console.log(obj)출력 결과
{ foo: 'bar' }
{ foo: 'bar' }
{ foo: 'bar', hello: 'world' }결과 분석
첫 번째 함수 updateRef에서는 지역 변수 x가 빈 객체 {}로 재할당되었지만, 이는 x라는 지역 변수의 참조만 바뀐 것일 뿐 원본 obj에는 어떤 변화도 없습니다.
반면 두 번째 함수 addHelloWorld에서는 y가 obj와 동일한 객체를 참조하고 있었기 때문에, y를 통해 객체의 내부 상태(속성 hello)를 변경하면 원본 객체에도 그대로 반영되어 { foo: 'bar', hello: 'world' }가 출력된 것입니다.
핵심 정리
자바스크립트에서 함수 인자는 항상 값으로 복사되어 전달됩니다. 원시 타입은 값 자체가 복사되고, 객체는 참조값이 복사됩니다. 따라서 함수 내부에서 매개변수를 재할당하면 원본에 영향이 없지만, 객체의 내부 속성을 직접 수정하면 원본 객체까지 변경된다는 점을 꼭 기억하세요.