Call by value (값의 복사)
Call by value는 값이 그대로 복사되는 방식이다. JS에서는 Primitive데이터타입이 Call by value 방식이 사용된다.
let a = 50;
let b = a; // a의 값을 복사해서 b에 대입
console.log(`a:${a}, b:${b}`); // 50, 50
b = 100;
console.log(`a:${a}, b:${b}`); // 50, 100
실제로는 b가 a와 같은 메모리주소값을 갖게되는 것이지만 표면적으로는 값을 그대로 복사해서 가지게 되는 형태이다.
function swap(val1,val2) {
let temp = val1
val1 = val2;
val2 = temp;
}
let a = 1, b = 2;
swap(a,b);
console.log(`a:${a}, b:${b}`); // 1, 2 두 변수의 값이 바뀌지 않았다.
함수의 인수도 Call by value방식으로 복사된다.
swap()함수는 두 변수의 값을 교환한다. 그러나 함수를 실행해도 두 변수의 값은 바뀌지 않았다.
그 이유는 a와 b는 primitive타입 데이터이기 때문에 val1, val2에 값이 '복사'되었고 따라서 a, b, val1, val2는 각각 자신의 값을 가지게 되었기 때문이다.
Call by reference (주소의 복사)
Call by reference는 데이터가 있는 공간(메모리의 주소)가 참조되는 것을 말한다. JS에서 '객체'는 Call by reference가 일어난다.
const userA = { id:"account", password:"1234" };
const userB = userA;
console.log(`${userA.id}, ${userB.id}`); // account, account
userB.id = "hello1234";
console.log(`${userA.id}, ${userB.id}`); // hello1234, hello1234
위 코드에서는 userB에 userA 객체를 할당하였다. 이 때 userB에는 userA의 id, password의 값이 복사되는것이 아닌 userA의 메모리 주소가 참조된다. 따라서 userA와 userB는 같은 메모리에 있는 데이터를 참조하는 변수이다.
function swap(val1,val2) {
let temp = val1.value;
val1.value = val2.value;
val2.value = temp;
}
const a = { value:1 };
const b = { value:2 };
swap(a,b);
console.log(`a:${a.value}, b:${b.value}`); // 2, 1 두 변수의 값이 바뀌었다.
위의 Call by value의 swap() 함수를 객체를 건네주는 형태로 바꾸었다.
val1, val2는 객체 a, b의 메모리 주소를 가지고 있기에 두 객체 a, b의 프로퍼티(value) 값이 정상적으로 바뀐다.
배열 또한 객체이기에 Call by reference가 일어나게 된다.
function swap(array) {
let temp = array[0];
array[0] = array[1];
array[1] = temp;
}
const arr = [1,2];
swap(arr);
console.log(`a:${arr[0]}, b:${arr[1]}`); // 2, 1
참조가 바뀌는 상황(객체를 재선언/재할당, 객체 리터럴)
두개의 변수가 같은 객체를 가리키고 있는 상황(위 코드의 userB, userA와 같이) 에서 한 객체의 프로퍼티를 리터럴 형식으로 변경(useB = {})하면 기존의 프로퍼티를 참고한 새로운 객체(힙에 새로운 공간이 만들어지고 새로운 주소가 주어짐)가 만들어진다.
let userA = { name:"song" };
let userB = userA
console.log(`${userA.name}, ${userB.name}`); // song, song
userB = { phone: "07077777777" }; // 리터럴 형식으로 phone 프로퍼티 추가
console.log(`${userA.phone}, ${userB.phone}`); // undefined, 07077777777
// 즉 userA와 userB는 서로 다른 객체
위의 코드에서 첫번째 console.log()까지는 userA와 userB가 같은 메모리주소를 참조하고 있다. 하지만 userB를 리터럴형식으로 재선언하면서 새로운 객체(새로운 주소를 가진)가 만들어지게 된다.
따라서 어떤 객체를 참조하는 변수를 선얼할 때는 const를 사용하거나 객체 리터럴이 아닌 (.)을 사용하는 것이 좋다.
참조)
Javascript의 인자전달 Call by value or reference - 라마개발일기 (lamarr.dev)
'바닐라코딩 사전학습 > JS' 카테고리의 다른 글
new 예약어 (0) | 2021.12.27 |
---|---|
객체 생성자 함수 (0) | 2021.12.27 |
콜스택 / 메모리힙 구조, 데이터저장 / 참조 원리 (0) | 2021.12.27 |
메모리 구조 / 변수 생성원리 / 가비지컬렉터 (0) | 2021.12.27 |
Primitive / Reference (0) | 2021.12.27 |