자바스크립트 타입과 값, 그리고 garbage collection

adam2·2020년 1월 4일
0

원시 타입(Primitive Type)

자바스크립트에는 6가지 종류의 원시 데이터 타입이 있다. 원시 데이터 타입은 쉽게 말하자면 자바스크립트에서 객체가 아닌 것들이며 값 그 자체로 저장된 것 이다. 마치 atom과 같다.

  • boolean
  • null
  • undefined
  • number
  • string
  • symbol

원시 타입은 값(value)으로 저장되고, 객체들은 참조(reference)로 저장된다. 아래 배열과 객체는 내용은 같지만 다른 곳을 참조하고 있기 때문에 false를 리턴.

"dog" === "dog";                        // true
14 === 14;                              // true

{} === {};                              // false
[] === [];                              // false
(function () {}) === (function () {});  // false

객체(Object)

객체는 원시타입은 아니지만 자바스크립트의 타입값 중 하나이다.

내장객체

내장 객체란 자바스크립트가 기본적으로 가지고 있는 객체들을 의미한다. 내장 객체가 중요한 이유는 프로그래밍을 하는데 기본적으로 필요한 도구들이기 때문이다.

Native 객체

  • Object
  • Function
  • Array
  • String
  • Boolean
  • Number
  • Math
  • Date
  • RegExp
var a = new String("Abc");

typeof a; // "object"     !!string이 아니다!!

자바스크립트는 원시값을 알아서 해당 객체 래퍼로 래핑해주기 때문에 다음과 같은 코드가 가능하다.

var a = "abc";
a.length; // 3
a.toUpperCase(); // "ABC"

reference

값 vs 레퍼런스 복사

자바스크립트는 원시타입을 복사할 땐 값복사, 객체는 레퍼런스 복사를 한다.

값복사

var a = 2;
var b = a;
b++;

a; // 2
b; // 3

b에 a의 2라는 값이 복사되어 초기화된다.

b의 값을 변경하면 b의 값만 3이 된다.
이렇게 두개의 변수가 완전히 독립성을 갖는 것을 값 복사 또는 깊은 복사 라고 한다.

레퍼런스 복사

var origin = [1, 2, 3, 4];
var copy = origin;
var obj = [1, 2, 3, 4];

origin[0] = 100;
origin; // [100, 2, 3, 4]
copy; // [100, 2, 3, 4]

console.log(origin == obj); // false
console.log(origin == copy); // true

origin은 배열의 시작원소 위치를 참조한다.(0x10) copy도 origin의 위치를 참조한다. (0x10)
두 변수는 같은 메모리 위치를 참조하기 때문에 독립적이지 않다.

function foo(x) {
  x.push(4);
  x; // [1,2,3,4]

  x = [4, 5, 6];
  x.push(7);
  x; // [4,5,6,7]
}

var arr = [1, 2, 3];
foo(arr);
arr; // [1,2,3,4]

arr을 인자로 넘기면 arr의 레퍼런스 사본이 x에 할당된다.
하지만 그 후 x = [4,5,6] 으로 새 값을 할당해도 초기 레퍼런스 arr가 참조하고 있던 값에는 아무런 영향이 없다. arr레퍼런스는 여전히 [1,2,3,4] 값을 바라보고 있다.

Garbage Collection

가비지 콜렉션은 자바스크립트 엔진의 백그라운드 프로세스로 동작한다. 가비지 콜렉션은 모든 객체들을 모니터링 하며 그것들이 접근 불가능하게 되었을 때 삭제하는 작업을 수행한다.

기본적인 가비지 콜렉션의 알고리즘은 마크 앤 스윕(Mark-and-sweep) 이라고 불린다.

  • 가비지 콜렉터는 루트를 획득하여 그들을 마크(기억)합니다.
  • 그리고 그들이 참조하고 있는 모든 것들에 방문하여 마크합니다.
  • 그리고 마크한 모든 객체에 방문하여 그들의 참조 역시 마크합니다.
  • 모든 객체들을 기억하고 나면 미래에는 같은 객체를 두번 방문하지 않습니다.
  • 루트로부터 접근 가능한 방문하지 않은 참조가 있다면 계속해서 반복합니다.
  • 마크되지 않은 모든 객체는 삭제됩니다.

루트가 참조하고 있는 모든 객체에 방문해 마크한다.

마크한 객체가 참조하는 것들도 마크한다.

가능할 때 까지 마킹을 한다.

방문이 불가능한(unreachables) 객체들은 접근 불가능한 것으로 간주되어 삭제한다.

  • 가비지 콜렉션은 자동으로 실행된다.
  • 객체는 그들이 접근 가능한 동안 메모리에 유지된다.
  • 참조가 된다는 것이 루트(Root)에서 참조 가능한것과 같은 말은 아니다 : 상호 참조하고 있는 객체들이 전체에서 보면 참조 불가능할 수 있다.

가비지 컬렉션이 작동하는 시기는?

reference

0개의 댓글