참조 (Reference)

참조 (Reference)

  • JavaScript에는 모두 일곱 가지의 타입이 존재한다.

  • 원시 타입(primitive type)

    • Boolean
    • Null
    • Undefined
    • Number
    • String
    • Symbol
  • 참조 타입(reference type)

    • Object

참조란?

  • 여기에서 참조(reference)란, 객체가 컴퓨터 메모리 상에서 어디에 저장되었는지를 가리키는 값이다.
  • JavaScript에서는 우리가 참조를 직접 읽거나 조작할 수 없다.
  • 하지만, 언어를 제대로 이해하기 위해서 참조가 무엇인지 알아야 할 필요는 있다.

  • 우리가 객체라고 생각하고 다루어왔던 값은 실제로는 객체에 대한 참조이다.

1
const obj = {}; // 변수 `obj`에는 객체에 대한 참조가 저장되었다.
  • 객체의 속성에 접근하면, JavaScript 엔진은 참조를 통해 메모리에 저장되어 있는 객체에 접근해서 해당 객체의 속성을 읽는다.
  • 이런 동작을 가지고 역참조(dereference)라고 한다.
1
2
const obj = { prop: 1 };
obj.prop; // `obj`를 통해 역참조된 객체의 속성을 읽어왔다.

함수 호출

  • 함수 호출 시에는 인수가 복사되어 매개변수에 대입된다.
  • 만약 함수 호출 시에 객체를 인수로 넘긴다면, 이 때 역시 실제로 복사되는 것은 객체 자체가 아니라 참조이다.
  • 그래서, 우리는 이 참조를 이용해 원본 객체의 내용을 변경할 수 있다.
  • 원본이나, 복사된 참조나 같은 객체를 가리키기 때문이다.
1
2
3
4
5
6
7
8
9
const obj = {};

function addProp(o) {
o.prop = 1;
}
// 변수 `obj`에 저장되어 있는 참조가 매개변수 `o`에 복사됩니다.
addProp(obj);

console.log(obj.prop); // 1

객체의 같음 (Equality)

  • 우리는 이제까지 === 연산자를 이용해서 두 값이 같은지를 판별해 왔다.
  • 그런데 객체에 대해서는 비교 연산 역시 오묘하게 동작한다.
  • 내용이 같은 두 객체를 === 연산자를 통해 비교해도, 결과값은 false로 나온다.
1
2
{prop: 1} === {prop: 1}; // false
[1, 2, 3] === [1, 2, 3]; // false
  • 위의 등호 연산자 역시, 객체의 내용을 비교하는 것이 아니라 객체의 참조를 비교한다.
  • 우리가 생성자나 리터럴을 이용해 객체를 생성하면, 객체는 매번 새로 생성되어 각각 메모리의 다른 위치에 저장된다.
  • 그래서, 내용이 똑같아 보이는 두 객체일지라도 그에 대한 참조는 서로 다른 것이다.

  • 당연하게도, 두 참조가 정말로 같은 객체를 가리키고 있다면 등호 연산자는 true를 반환한다.

1
2
3
const obj1 = {};
const obj2 = obj1;
obj1 === obj2; // true
  • 프로그램을 작성하다가 객체에 대한 비교를 하는 코드를 짜고 있는 자신을 발견하게 되면,
    지금 객체의 내용을 비교하려고 하는 것인지, 또는 객체의 참조를 비교하려고 하는 것인지를 꼭 생각해보자.
  • 객체의 내용을 통해 비교하고 싶다면, 깊은 비교 기능을 지원하는 라이브러리를 이용하거나,
    정확히 어떤 내용을 비교하고 싶은지를 가지고 함수 혹은 메소드를 작성한 후 그것을 이용하자.