자바스크립트 call by value or call by reference


모든 OOP 언어에서다루고 있는 부분 이라고 할 수 있는 값(value)참조값(ref value)에 대해 "자바스크립" 에서는
어떻게 다루고 있는지 알아 보도록 하겠습니다.


 var value = '';
    var ref = {};
    
    function callbyvalueReference(value, ref) {

        value += 'value';
        ref.name = 'reference';
    }


    callbyvalueReference(value, ref);

    alert(value); // value
    alert(ref.name); // reference


1. value 변수와 ref 변수에 각 각 "값" 과 "객체"를 선언 및 정의 합니다.
 

2. 이렇게 정의된 2개의 변수를  fn(value, ref);  호출 합니다.

3. 값의 복사본인 함수 매개변수 value는 해당 함수의 지역 변수로 선언되고 정의 됩니다.
 

"즉, 전역변수로 선언 및 정의된 value의 문자열과는 "+=" 연산자를 통해 합쳐 지지 않는
다는 것을 말합니다."


4. 하지만 객체를 정의한 ref 전역 변수는 함수의 매개변수로 "값" 과 "복사복" 이 아닌 값에 의한 참조지역변수로
전달 되었기 때문에 내부에서 언제든 참조값 수정이 가능하게 되었습니다.



P.S 문자열 복사와 전달

위의 설명에서 자바스크립트에서 객체는 참조만 전달된다고 하였습니다.

그렇다면 문자열은 기본타입인 값(call by value)에 의한 참조이며, 매개변수 전달 시 값에 복사본이 전달된다는 말이 됩니다.

그러나 문자열의 길이는 임의적이기때문에 문자열을 바이트 단위로 복사하거나 전달, 비교하는 일은 매우 비효율적인 이기때문에 문자열은 참조 타입 형태로 구현되었다고 가정하는 것이 더 적절합니다.

위의 내용처럼 문자열이 값에 대한 참조인지 알 수 있는 방법은 없으나, 문자열 비교를 통해 값에 의해 비교되는지 참조로 비교되는지 알 수는 있습니다.

  1. // 만약 두 문자열이 값에 의해 비교되면 두 문자열은 동일할 것이고 참조에 의해 비교되면 동일하지 않을 것이다.
  2.  
  3. var s1 = 'hello';
  4. var s2 = 'hell' + 'o';
  5.  
  6. alert(s1 === s2); //true
  7.  
  8. var obj1 = {
  9.     str: 'hello'
  10. }
  11.  
  12. var obj2 = {
  13.     str: 'hell' + 'o'
  14. }
  15.  
  16. alert(obj1.str === obj2.str); //true


아래는 간단한 객체 상속 관계에서 참조값을 다루는 코드예제 입니다.

  1. function fn(){
  2. }
  3.  
  4. fn.prototype = {'arr': []};
  5.  
  6. new fn().arr.push(1);
  7.  
  8. alert(new fn().arr); // 1


1. fn() 함수 객체가 생성 됩니다.

2. fn() 함수 객체의 프로토타입 맴버에 객체({'arr': []})를 추가 합니다.

3. fn() 객체의 프로토타입 맴버에 추가된 객체의 arr 배열 속성에 1을
push() 함수로 1을 추가 합니다. 


4 . 
alert(new fn().arr); // 1  에서 "1" 이 반환되는 이유는? 

"자바스크립트" 에서 객체는 참조만 전달되기 때문이다. 즉, 자식( new fn() ) 객체 에서 속성 ({'arr': []})  값을 수정하면 부모 객체 속성 ({'arr': []}또한 수정되어 버립니다.