[Javascript] 값에 의한 전달, 참조에 의한 전달 (feat. 공유에 의한 전달)

Jaehyun Park·2023년 10월 21일

모던 자바스크립트 deep dive를 공부하다가 원시 값과 객체 비교 파트에서 값에 의한 전달, 참조에 의한 전달, 공유에 의한 전달이라는 개념이 나왔다.

세 개념 모두 ECMAScript의 용어는 아니고 다른 프로그래밍 언어에서 사용되는 용어라고 하여 이 개념이 무엇인지 좀 더 찾아보았다.


1. 값에 의한 전달 (Pass by Value)

  1. 할당 연산자(=)로 변수에 값을 지정해주면, 하나의 메모리 공간에 변수의 값이 저장되며 변수(변수명)은 식별자로써 값이 저장되어 있는 메모리의 주소를 가리키게 된다. (값이 저장되는 것이 아니다.)
  2. 함수에 파라미터로 전달되는 것은 변수의 값 자체이며, 변수의 복사본이 함수로 전달되는 것이다.
  3. 함수 내에서 매개변수를 변경해도 호출된 곳의 변수에는 영향을 미치지 않는다.
  4. 숫자, 문자열, 불리언, null, undefined와 같은 원시 값들이 여기에 해당한다. 함수로 전달될 때 값이 복사되어 전달된다.

예시 코드:

function multiplyByTwo(value) {
  value = value * 2;
  console.log("Inside function:", value);
}

let number = 3;
multiplyByTwo(number);
console.log("Outside function:", number);

출력 결과:

Inside function: 6
Outside function: 3

코드의 흐름도:

1. multiplyByTwo 함수에 number라는 값 3이 전달됨.
2. 함수 내부에서 value는 2배가 되어 6이 됨.
3. 함수 외부에서 number는 여전히 3.

=> 원시 값은 변경 불가능한 값이기 때문이라고 볼 수 있겠다. 따라서 함수 내부의 value와 함수 외부에 선언된 number는 각각 다른 메모리 주소를 참조하기 때문에 변수 내부에서 값의 수정이 일어나도 식별자가 다르기 때문에 다른 값을 가지게 된다.


2. 참조에 의한 전달 (Pass by Reference)

  1. 함수에 인자로 전달되는 것은 변수의 메모리 주소(참조)이며, 변수의 원본이 함수로 전달된다.
  2. 함수 내에서 파라미터를 변경하면 호출된 곳의 변수도 변경된다.
  3. 객체, 배열, 함수와 같은 복합 데이터 타입들이 여기에 해당한다. 함수로 전달될 때 참조가 전달되어, 원본 객체를 참조하게 된다.

예시 코드:

function addToProperty(obj) {
  obj.property = obj.property + 5;
  console.log("Inside function:", obj.property);
}

let myObject = { property: 10 };
addToProperty(myObject);
console.log("Outside function:", myObject.property);

출력 결과:

Inside function: 15
Outside function: 15

코드의 흐름도:

1. addToProperty 함수에 myObject라는 객체가 전달됨.
2. 함수 내부에서 객체의 property에 5가 더해져 15가 됨.
3. 함수 외부에서 myObject의 property는 15.

=> 원시 값을 가지는 변수와는 다르게, 변수에 객체를 저장하면 변수는 '참조값'을 가지게 된다.
참조값이란 C나 C++에서 사용하는 포인터와 비슷한 개념으로 실제 객체 값이 저장되어 있는 메모리 주소를 가리키는 것을 말한다. 즉, myObj라는 변수에 { name: 'popo' }라는 객체를 저장한다면, myObj에는 0x003이라는 { name: 'popo' } 객체 값이 저장된 메모리 주소가 저장되고, myObj를 참조하면 메모리 주소 0x003가 참조되어 0x003에 저장되어 있는 { name: 'popo' }가 불러와지는 것.

let myObj1 = { name : 'popo' };
let myObj2 = myObj1;
myObj2.age = 25;

console.log(myObj1);  // { name: 'popo', age: 25 }
console.log(myObj2);  // { name: 'popo', age: 25 }

즉, 같은 메모리 주소(객체가 저장된 곳을 가리킴)를 참조하고 있기 때문에 함수 내부에서나 다른 변수에서 생성, 제거, 수정 등 변화가 일어나면 원본에도 변화가 일어나는 것이다.


3. 공유에 의한 전달 (Pass by Sharing)

  1. 값에 의한 전달과 참조에 의한 전달의 중간 개념으로 볼 수 있다.
  2. 함수에 전달되는 것은 변수 값이지만, 참조 형태로 전달되는 것처럼 동작한다.
  3. 함수 내에서 매개변수를 변경하면 호출된 곳의 변수에 영향을 줄 수 있다.
  4. 몇몇 언어에서 사용되며, 자바의 객체 전달 방식이 이에 해당한다.

예시 코드:

function changeName(person) {
  person = { name: "Alice" };
  console.log("Inside function:", person.name);
}

let user = { name: "Bob" };
changeName(user);
console.log("Outside function:", user.name);

출력 결과:

Inside function: Alice
Outside function: Bob

코드 흐름도:

1. changeName 함수에 user라는 객체가 전달됨.
2. 함수 내부에서 person에 새로운 객체가 할당되지만, 이는 함수 외부의 user와는 독립적임.
3. 함수 외부에서 user의 name은 여전히 "Bob".
profile
Technologically solve everyday challenges

0개의 댓글