본문 바로가기

javascript

javascript call by value 와 call by reference 헷갈리는 점 정리

자바스크립트는 call by value와 call by reference에 대한 개념에 있어서 c언어와는 조금 다른 특징을 가지고 있습니다. 이 부분을 중점으로 시각화하여 정리했습니다. call by value와 call by reference에 대한 개념을 숙지하지고 포스팅을 보시면 도움이 됩니다.

결론

javascript는 기본적으로 항상 call by value입니다.

그렇기 때문에 파라미터로 넘어온 값들을 변경해도 원본 데이터는 변하지 않습니다. 하지만 참조형 타입의 데이터인 경우 속성을 변경할 경우 원본 데이터도 같이 변하는 경우가 있습니다. 자바스크립트는 기본적으로 call by value라고 했지만 원본 데이터가 변할 수도 있다고 하는 이유는 무엇일까요? 밑의 예시 들에서 그 이유를 설명합니다.

우선 문자열(원시 타입)의 경우 어떻게 될까?

원시 타입의 데이터인 경우 메모리에서 주소값을 거치지 않고 곧바로 데이터를 보관합니다. 따라서 따져볼 필요 없이 call by value로서 데이터가 함수로 전달됩니다. 그러하기에 복사된 데이터를 수정해도 원본 데이터는 수정되지 않습니다.

function change_val(name_arg) {
    var name_arg = "jongyeol"; 
    return; 
}

function main() {
    var name = "justin"; 
    console.log("name before call: ", name); // "justin" 
    change_val(name); 
    console.log("name after call: ", name);  // "justin" 
    return; 
}

main();

 

배열(참조 타입)의 경우 파라미터로 들어온 값을 바꾸면 원본 데이터는 어떻게 될까?

많은 사람들이 javascript에서 배열은 레퍼런스 타입이기에 call by reference로 작동하는 것으로 알고 있지만 상황별로 따져봐야 합니다. 첫째, 주소 값을 재할당하는 경우둘째, 참조형 데이터의 속성을 변경하는 경우입니다.

첫째, 주소값을 재할당하는 경우

- 자바스크립트에서는 참조 타입을 넘기면 참조값에 대한 복사본을 만들어서 넘깁니다.

- 즉, arr의 주소 값이 복사되어 넘어갑니다.

- arr_arg에 temp의 주소 값이 재할당 되는 순간 arr과 arr_arg는 서로 다른 값을 바라보는 주소 값을 가지게 됩니다.

- 그러므로 원본 arr은 변화가 없습니다.

function change_val(arr_arg) { 
    var temp = [1,2,3,4];
    arr_arg = temp; // 재할당, 즉 다른 주소값(temp)를 바라보게 됨 
    return; 
}

function main() { 
    var arr = [1, 2, 3];
    console.log("value name, arr before call: ", arr); // 1 ,2, 3 (0x01) 
    change_val(arr); 
    console.log("value name, arr after call: ", arr); // 1, 2, 3 (0x02) 
    return;
}

main();

 

둘째, 배열의 속성을 추가하거나 변경하는 경우

- 자바스크립트에서는 참조 타입을 넘기면 참조값에 대한 복사본을 만들어서 넘깁니다. (위와 동일) 

- 즉, arr의 주소 값이 복사되어 넘어갑니다. (위와 동일)

- arr_arg에 push를 통해 속성을 변경합니다.

- 주소 값이 재할당 되지 않았고 push를 통해 속성만 추가했기 때문에 원본 데이터에도 push 된 4가 들어가 있습니다.

function change_val(arr_arg) {
  arr_arg.push(4);
  return;
}

function main() {
  var arr = [1, 2, 3];
  console.log("value name, arr before call: ", arr); // 1 ,2, 3 (0x01)
  change_val(arr);
  console.log("value name, arr after call: ", arr); // 1, 2, 3, 4 (0x01)
  return;
}

main();