본문 바로가기
개발/JavaScript

[JavaScript] call by value, call by reference, call by sharing

by coking 2023. 2. 7.

얼마 전 다른 글 정리하면서 call by value와 call by reference관련해서 보게 되었는데 생각해 보니 javascript에서는 어떻게 돌아가는지 명확하게 공부하거나 찾아보지는 않고 그냥 원시형, 참조형으로 값에 어떻게 영향이 가는지 정도만 알고 사용하고 있어서 좀 더 알아보니 새로운 개념들을 알게 되어서 정리한다!!

 

call by value, call by reference란??

함수를 호출할 때 argument 값의 타입이 어떤 것이냐 하는 것인데 argument가 기본형이면 call by value, 참조형이면 call by reference이다.  

  • call by value
    • 원시형 값의 의한 호출 
    • 원본 값을 복사하여 parameter로 전달
  • call by reference
    • 참조형 값의 의한 호출
    • 원본 값의 메모리 주소값을 parameter로 전달 

 

call by value 예시 코드 

function valueCheck(num1, num2) {
  const result = num1 + num2;

  num1 = 0;
  num2 = 0;

  return result;
}

const number1 = 1;
const number2 = 2;

const result = valueCheck(number1, number2);

console.log('number1: ', number1, 'number2: ', number2); // number1:  1 number2:  2
console.log('result: ', result); // result:  3

valueCheck 함수의 인자로 전달되는 number1, number2의 값이 원시형(number) 타입이기 때문에 값의 복사본이 전달되어 함수 내에서 해당 변수를 변경해도 원본 값에는 영향을 미치지 않는다. 

 

 

call by reference 예시 코드

function referenceCheck(obj2) {
  obj2.a = 7;
}

let obj1 = { a: 5, b: 8 };

referenceCheck(obj1);

console.log(obj1);	// { a: 7, b: 8 }

referenceCheck 함수의 인자로 전달된 obj1의 값이 참조형(object) 타입이기 때문에 값의 주소가 전달되어 함수 내에서 해당 변수를 변경하면 원본 값에 영향을 미침

 

그러나!!!

function referenceCheck(obj1, obj2) {
  obj1.a = 7;
  
  obj2 = 10;
}

let obj1 = { a: 5, b: 8 };
let obj2 = { a: 5, b: 8 };

referenceCheck(obj1, obj2);

console.log(obj1);	// { a: 7, b: 8 }
console.log(obj2);  // { a: 5, b: 8 }

이 코드 예시를 잘 보면 obj1은 잘 변경된 걸 확인할 수 있다. 근데 obj2는 변경되지 않았다 분명 객체를 인자로 넘겼고 객체는 참조 타입이다. 만약 인자 값들이 call by value로 작용했다면 obj1은 변했으면 안 된다. call by reference로 작용했다면 obj2가 변했어야 한다. 두 경우 다 성립하지 않은 것이다. 왜 이런 결과가 나온 것일까??  

 

 

그 해답은 call by sharing에서 찾을 수 있다.

 

call by sharing이란??

함수의 인자로 전달된 값이 참조형 타입일 때 그 주소값을 바로 전달하는 것이 아닌 복사된 주소값을 전달하는 것이다.  그러므로 그 주소가 가리키는 요소에는 직접 접근해 영향을 미칠 수 있을지라도 그 원본 값에는 영향을 미치지 못한다.

 

이런 식으로 가리키고 있는 주소는 같지만 메모리 주소가 복사되어 다른 값이 들어가는 것이다. 

function referenceCheck(target1) {
  target1 // 메모리 주소: 0x002
  target1.a = 7;  // 메모리 주소: 0x002 하지만 가리키는 주소 0x001
  
  target1 = 10; // 메모리 주소가 변동됨 => 메모리 주소: 0x003
  target1.b = 9;  // 메모리 주소: 0x003

  console.log(target1);  // 10,  메모리 주소: 0x003
}

let obj1 = { a: 5, b: 8 };  // 메모리 주소: 0x001

referenceCheck(obj1);

console.log(obj1);	// { a: 7, b: 8 },  메모리 주소: 0x001

 

그러나 처음에 서로 가리키고 있는 값은 0x001( {a:5 , b:8} )로 같다는 것을 명심하자 target1.a = 7; 이런 식으로 직접 값에 접근한다면 영향을 미친다는 것이다. 하지만 target1에 새로운 값을 넣으면 메모리 주소가 변동되고 가리키는 값도 완전히 달라진다.  결론적으로 이 referenceCheck 함수 안에서 target1이 변동되지 않은 상태에서 가리키고 있는 요소의 값을 바꾸지 않는 이상 target1을 어떻게 바뀌든 복사된 주소의 값이 바뀌는 것이다!!


이런 식으로 call by sharing이 활용되는 언어는 JavaScript 말고도 Python이 존재한다고 하며 정리하면서도 정말 어려운 개념이라 생각보다 쉽지 않았지만 많은 분들에게 도움이 되길 바란다!!

 

 

 

댓글