Call by Value vs Call by Reference [JAVASCRIPT]
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로 넘겨주었다. 아래 그림과 같다.
그리고 parameter[0]=0
으로 값을 변경해줬다. 출력 결과는 [0,2,3,4]
로 원본 배열인 callee의 0번째 index
값이 변경되었음을 확인할 수 있다.
이러한 원리로 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];
자바스크립트는 항상 call by value 방식만 존재한다고 한다. 결국, 변수가 가리키는 메모리에 적재되어 있는 값을 복사해 전달하기 때문이다.
- call by value : 값을 복사 후 전달
- call by refernce : refernce를 복사 후 전달
Leave a comment