2022. 06. 추가) 공부를 더 하고 보니 이 글은 틀린 내용이 포함되어 있습니다. 정확히 말하자면 primitive, 참조 타입 모두 데이터에 대한 주소 값을 저장하는 것이 맞습니다. 그러나 그 데이터가 객체이냐, 아니면 실제 값이냐의 차이인 것으로 보아야 합니다. 추후 해당 포스팅을 수정하도록 하겠습니다.
결론부터 이야기하면 정답은 바로 call by value 이다.
흔히들 기본 타입은 call by value, 참조 타입 (객체 타입)은 call by reference로 동작한다고 잘못 알고있다.
그러나 자바스크립트는 항상 call by value로 동작한다. stackoverflow에서 좋은 예제 코드를 찾았다.
function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
// 결과
10
changed
unchanged
changeStuff라는 함수가 있다. 해당 함수에 세 개의 인자를 넘겨주는데, 각각 number, object, object이다.
만약 JS가 call by reference라면, obj2의 값이 함수 내부에서 새로운 객체로 변해야 한다. 즉 obj2는 함수 실행 후에 { item: "changed" } 로 바뀌어야 한다. 그러나 실행 결과를 보면 그렇지 않다. 당연하겠지만 num의 경우도 마찬가지이다.
일단 call by reference가 아니라는 것은 알겠다. 그런데 num이야 기본 타입이니 이해가 쉽지만, obj2는 왜 이렇게 동작할까?
이유는 간단하다. 참조 타입의 경우, 해당 객체의 주소값을 value로 가지는 타입이다. 즉, 참조 타입의 value는 주소이다.
이제 다시 call by value라고 생각하고 코드를 보자. obj1이라는 변수는 어떤 객체를 가리키는 주소값을 value로 가진다. 이 value값이 함수로 전달되기 때문에, b.item을 변경하는 것은 즉 obj1이 가리키는 obj1.item을 변경하는 것과 동일하다.
obj2도 보자. obj2라는 변수가 가리키는 어떤 객체를 가리키는 주소값이, 함수 내에 c라는 변수의 value로 저장된다. 함수 내에서 c라는 변수의 value에 새로운 객체의 주소가 할당됨을 알 수 있다. c는 어차피 함수 내의 지역변수이므로, 함수가 끝남과 동시에 정리된다. 따라서 실행 결과를 보면 obj2에는 영향을 줄 수 없다.
'개발 > JS' 카테고리의 다른 글
[Typescript] array, object 를 literal 타입으로 변환하기 (0) | 2021.09.25 |
---|---|
새로고침 시에도 redux store 유지하기 (0) | 2021.08.25 |
[Typescript] --downlevelIteration 에 대해서 (0) | 2021.08.09 |
[Javascript] var, let, const 의 호이스팅과 스코프 (0) | 2021.05.31 |
댓글