평가 전략 (evaluation strategy)
- 표현식(expression)이나 함수를 계산하거나 값을 평가하는 방법.
- 함수가 인자(argument)를 받아 매개변수(parameter)로 전달될 때의 방법.
- 프로그래밍 언어와 환경에 따라 다른 평가 전략을 사용함.
- 매개변수(parameter)
- 인자 (Argument)
- 매개변수는 함수 정의에서 사용되는 변수이고, 인자는 함수를 호출할 때 실제로 전달되는 값. 함수를 호출할 때 인자는 함수 내부로 전달되고, 함수 내부에서 매개변수로 받아 사용됨.
JS의 평가 전략
Call by Value (값에 의한 호출)
- 원시 값(primitive value)은 Call by Value 방식을 따름.
- 함수에 인수(argument)를 전달할 때, 해당 인수의 값(value)이 복사되어 매개변수로서 내부로 전달.
- 함수 내부에서 해당 값의 복사본을 사용하며, 함수 내부에서 복사본을 변경하더라도 호출자(원본; caller)에 영향을 주지 않음.
function changeValue(x) {
x = 5;
}
let a = 10;
changeValue(a);
console.log(a);
Call by Sharing (공유에 의한 호출 또는 값에 의한 공유)
- 객체 (Object)는 Call by Sharing 방식을 따름.
- Call by Sharing은 Call by Value와 Call by Reference 사이의 중간 개념.
- 함수에 인수(argument)를 전달할 때, 해당 인수의 참조(reference)가 복사되어 매개변수로서 내부로 전달.
- 객체는 함수 내부에서도 호출자와 동일한 객체를 참조.
- 내부에서 객체의 프로퍼티를 변경하면 호출자(원본; caller)에게도 변경 내용이 반영됨.
- 하지만, 내부에서 해당 객체 자체를 새로운 객체로 교체하는 경우(새로운 객체를 할당하는 경우), 호출자에게 영향을 주지 않음.
function modifyObject(obj) {
obj.name = "Alice";
obj = { name: "Bob" };
}
let myObject = { name: "John" };
modifyObject(myObject);
console.log(myObject.name);
JS에서 Call by Reference 용어를 사용하지 않는 이유
- JS는 C, C++ 과 같은 언어처럼 포인터나 메모리 주소 값에 접근하는 연산자가 없음.
- 때문에 객체(Object)를 함수에 전달할 때, 객체의 "참조가 복사"되어 전달됨.
- 이는 "참조"를 사용하고 있는 것처럼 보일 수 있으므로 Call by Reference와 유사한 동작을 보이지만, 참조(주소)를 한번 더 콜스택(call stack)에 복사하여 사용함을 의미.
- Call by Value를 기본적으로 따르는 것에 가까움.
- 아래와 같이 재할당을 하는 순간 함수 내부의 매개변수(참조 주소)는 다른 객체의 참조 주소로 변하기 때문에, 호출자(원본)에게 영향을 줄 수 없음.
function modifyObject(obj) {
obj = { name: "Bob" };
}
let myObject = { name: "John" };
modifyObject(myObject);
console.log(myObject.name);
- 그러므로 JavaScript에서는 값 복사(Value Copy)와 참조 복사(Reference Copy)라는 용어를 사용하여 이러한 동작을 설명하는 것이 더 명확함.
- c++ 등의 언어에서에서는 Call by Reference를 사용하고 python, java, ruby, javascript에서는 Call by Sharing 전략을 사용.