2.5 값 vs 레퍼런스

jude·2022년 2월 1일
0

you don't know js

목록 보기
18/30
post-thumbnail

책에는 헷갈리게 값-복사, 레퍼런스-복사 라고 써있지만 간단히 말해
불변값과 가변값 이라고 보면 된다.

불변값(immutable) - null, undefined, string, number, boolean, symbol
가변값(mutable) - 나머지 배열, 객체, 함수 등 합성 값들

var a = 2;
var b = a; // 'b'는 a의 값 2를 바라본다.
b++;
a; // 2
b; // 3 메모리에서 새롭게 추가된 숫자 3을 바라보게 된다.

var c = [1,2,3];
var d = c; // 'd'는 'c'가 바라보는 메모리에 선언된 '[1,2,3]'값을 같이 바라본다.
d.push( 4 );

// 같은 메모리 공간을 바라보고 있기 때문에 'd'의 값을 변경하면 'c'의 값도 같이 변경된다.
c; // [1,2,3,4]
d; // [1,2,3,4]

할당은 얘기가 다르다.

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

b = [4,5,6] // 'b'에 새로운 값을 할당하면 기존에 바라보고 있던 메모리를 놔두고, 새로운 메모리 공간을 바라보게 된다.
a; // [1,2,3]
b; // [4,5,6]

함수 인자는 헷갈리는 부분이다.

function foo(x) {
  x.push( 4 );
  x; // [1,2,3,4]
  
  x = [4,5,6];
  x.push( 7 );
  x; // [4,5,6,7]
}

var a = [1,2,3]

foo( a );

a; // [1,2,3,4]

사실 이렇게 쓰는 경우가 많이 있을지 모르겠지만 주의가 필요해 보이긴 하다.
매개변수를 넣어서 로직을 처리 하고, 결과값을 result 로 반환하는 것이 일반적이라고 생각할 수 있다.
또한 배열값에 할당을 하는 것은 덮어 쓰겠다는 행위 자체이기 때문에 저런 방법은 위험해 보인다.


function foo(x) {
  x.push( 4 );
  x; // [1,2,3,4]
  
  x.length = 0; // 기존 배열을 즉시 비운다.
  x.push( 4, 5, 6, 7 );
  x; // [4,5,6,7]
}

var a = [1,2,3];

foo( a );

a; // [4,5,6,7]

조금 헷갈리지만, 잘 생각해보면 x.length는 값에 할당하는 것이 아니고 객체에 할당하는 것이다.
객체는 가변값이다.
그래서 '[1, 2, 3]'이 아니라 '[4, 5, 6, 7]'

배열을 함수의 인수로 넣었을 때 원본 값이 바뀌지 않으려면 foo( a.slice() ); 와 같이 넣으면
함수 안으로 사본(얕은 복사)이 들어가게 되어 원본 훼손을 막을 수 있다.

Array.prototype.slice()는 인수가 하나도 없을 시,
첫번째 인자부터 마지막 인자까지의 원소들로 이루어진 새로운 배열을 반환한다.


function foo(wrapper) {
  wrapper.a = 42;
}

var obj = {
  a: 2
};

foo( obj );
obj.a; // 42

x.length 프로퍼티를 할당하여 수정한것처럼 obj.a도 가변값으로 변경이 된다.


let a = new Number( 2 )
console.log(typeof a); // "object"
function foo(x) {
  x = x + 1;
  x; // 3
}

var a = 2;
var b = new Number( a ); // 'Object(a)'도 같은 표현이다.

foo( b );
console.log( b ); // 2

그럼 숫자를 생성자 함수 호출 식으로 래핑해서 오브젝트 형태로 함수 인자로 넣으면 변경이 가능할까?

하지만 결과는 예상과 달리 2이다.

숫자는 원시 불변값이기 때문에 매개변수 x는 Number 객체에서 자동으로 언박싱되어 추출되고,
때문에 함수 밖에서 선언한 a, b는 그대로 2인 것이다.

이렇게 사용하는 것은 확실히 일반적인 사용방법이 아니다.
하지만 이런식으로 작동한다는 것을 알아두면 좋을 듯.

profile
UI 화면 만드는걸 좋아하는 UI개발자입니다. 프론트엔드 개발 공부 중입니다. 공부한 부분을 블로그로 간략히 정리하는 편입니다.

0개의 댓글