Call by Value vs Call by Reference [JAVASCRIPT]

2 minute read

call by value, call by reference의 개념과 자바스크립트 내에서는 어떻게 사용되는지 알아보자.


사실 이 포스팅을 작성하게 된 계기는 프로그래머스 자물쇠와 열쇠 이 문제를 풀이하다 ‘맞왜틀’에 빠졌기 때문이다. 배열 argument를 함수의 매개변수로 넘겨주며, 기본 배열 값의 변경되어 문제가 발생했다. 개념의 중요성을 다시 한번 느끼게 된다.

시작하기에 앞서, parameter 와 argument의 정의를 정리해봤다. Call by value, Call by Reference를 이해하기 위해 참고하면 좋을 것같다.

  • [참고] parameter vs argument
parameter는 함수 혹은 메서드내에서 정의되는 변수명이다.
argument는 함수 혹은 메서드를 호출할 때 전달하거나 입력되는 실제 값이다.

ex)

function test(para1,para2){
	return para1 + " " + para2;
}

// test 함수 내에 정의된 para1, para2는 parameter이다.

test(argu1,argu2);
// test 함수를 호출할 때 전달되는 argu1, argu2는 argument이다.


Call by value, Call by Reference란 무엇인가?

본격적으로 argument를 함수 혹은 메소드의 매개변수로 전달하는 두 방식에 대해 알아보자.

Call by value - 값을 전달한다.
Call by Refrence - 참조 값을 전달한다.


Call by Value

call by value의 특징은 이렇다.

  • argument가 값으로 넘어온다.

  • 값이 넘어올 때, 값을 복사하여 넘겨준다.
  • 호출하는 곳에서 값을 복사하여 넘겨주기 때문에, 호출 당한 곳에서 호출자의 argument 값을 변경할 수 없다. 즉, 원본 argument 값이 변경 될 위험이 없다.
  • Call by value 타입에는 number, string, boolean 등이 있다.
let callee="피 호출자";

function TryChangeCallee(parameter){
    parameter="호출자";
}

TryChangeCallee(callee); // 호출자

console.log(callee); // 출력 : 피 호출자

Call by value 타입인 string “피 호출자”를 함수의 parameter로 넘겨줬다. TryChangeCallee 함수에서 변수 callee의 값이 변경되지 않는 것을 확인할 수 있다.


Call by Reference

call by reference의 특징은 이렇다.

  • argument로 reference를 넘겨준다.
    • reference는 메모리 주소를 담고있는 혹은 가리키는 변수이다.
  • reference 자체를 넘기기 때문에 call by value와 다르게 값을 복사해 넘기는 형태가 아니다.
  • 호출하는 곳에서 참조 값을 넘겨주기 때문에, 호출 당한 곳에서 호출자의 argument 값을 변경할 수 있다. 즉, 원본 argument 값이 변경 될 위험이 발생한다.
  • Call by Reference 타입에는 array, object, date 등이 있다.
let callee=[1,2,3,4];

function TryChangeCallee(parameter){
    parameter[0]=0;
}

TryChangeCallee(callee); // 호출자

console.log(callee); // 출력 : [0,2,3,4];

이번에는 call by reference 타입인 array를 함수의 parameter로 넘겨주었다. 아래 그림과 같다.

image

그리고 parameter[0]=0 으로 값을 변경해줬다. 출력 결과는 [0,2,3,4]로 원본 배열인 callee의 0번째 index값이 변경되었음을 확인할 수 있다.

image

이러한 원리로 callee와 같은 값을 참조하고 있는 parameter에서 특정 값이 변경되면 callee의 값도 변경되는 것이다.

  • 0x001,0x002, 0x003은 임의로 메모리주소를 지정한 것이다.
  • 메모리주소 - 메모리 위치에 대한 식별자, 메모리가 존재하는 공간


Refernce 원본을 유지하는 방법

그렇다면 call by reference로 값을 넘겨줄 때, 어떻게 원본 reference 값이 변경되지 않고 parameter로 넘어온 reference를 사용할 수 있을까?

답은 새로운 객체를 생성하고, 매개변수 값을 이 새로운 객체에 할당하는 것이다.


let callee=[1,2,3,4];
function TryChangeCallee(parameter){
    let newarr=Array.from(Array(4));
    /*
       원소 하나하나를 복사해줘야 Deep copy(깊은 복사)가 된다.
       => 새로운 메모리가 할당되고, 복사된다.
       newarr=parameter는 shallow copy(얕은 복사)가 된다.
       =>  참조값에 할당된다.
    */
   
    for(let i=0;i<parameter.length;i++){
        newarr[i]=parameter[i];
    }
    newarr[0]=0;
}

TryChangeCallee(callee); // 호출자

console.log(callee); // 출력 : [1,2,3,4];

image

자바스크립트는 항상 call by value 방식만 존재한다고 한다. 결국, 변수가 가리키는 메모리에 적재되어 있는 값을 복사해 전달하기 때문이다.

  • call by value : 값을 복사 후 전달
  • call by refernce : refernce를 복사 후 전달


Reference

Leave a comment