4 분 소요

자바스크립트가 값을 저장하는 방식

  • Data 영역에는 null, undefined, 그리고 평가 단계에서의 변수 주소 (8bit)
  • Stack 영역에는 크기가 변할 수 없는 변수의 값이 저장 -> 원시 타입
  • Heap 영역에는 크키가 변할 수 있는 변수의 값이 저장 -> 객체 타입

변수 (Variable) : 하나의 값을 저장할 수 있는 메모리 공간

변수 = 선언 + 식별자 + 타입 + 값 + 소코프

  • 자바스크립트는 개발자가 메모리 주소를 통해 값에 직접 접근하는 메모리 제어를 허용하지 않음
  • 변수 이름을 어떤 값을 구별해 식별 가능한 고유한 이름이란 의미에서, 식별자 (Identifier) 라고도 함
    • 식별자는 값이 아닌 메모리 주소를 기억하고 있어, 식별자로 메모리 공간에 저장된 값에 접근
var userId = 1;
var userName = 'John';

var user = { id: 1, name: 'John' };

var users = {
    { id: 1, name: 'John' }
}
  • 변수 선언 (variable declaration)을 통해 변수를 생성 → var, let, const 키워드
    • 변수에 값을 할당하지 않았으면, 자바스크립트 엔진에 의해 undefined 값이 할당되어 초기화
    • 선언하지 않은 식별자에 접근하면 참조 에러 (ReferenceError)가 발생

리터럴 (literal) : 사람이 이해할 수 있는 문자나 기호를 통해 값을 생성하는 표기법

  • 값 (value) : 표현식이 평가되어 생성된 결과
10 + 20; // 30

  • 표현식 (expression) : 값으로 평가될 수 있는 구문
    • 구문 (statement) : 프로그램을 이루는 기본 단위이자 최소 실행 단위 (선언문, 할당문, 조건문, 반복문 등)
      • 토큰 (token) : 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소

데이터 타입 (Date Type) : 값의 종류

  • 숫자 타입 : 정수 및 실수를 모두 포함하는 타입으로 존재 (모든 수를 실수로 처리)
    → 큰 수를 위한 BigInt 타입과는 다름! (BigInt는 객체 타입으로, 모든 수를 정수로 처리)
  • 문자열 타입 : ‘’, “”, ``로 문자열을 감싼 텍스트 데이터
    • 템플릿 (template) 리터럴 : 로 감싼 문자열 (ES6``부터 도입)
      • 멀티라인 문자열 : 백슬레시 (\n) 없이 개행 가능
      • 표현식 삽입 : +으로 ${}로 감싼 표현식을 문자열로 변환해 삽입할 수 있음
  • 불리언 타입 : 참 (true)과 거짓 (false) → 제일 작은 값 (1bit)
  • 심볼 (symbol) 타입 : 변경 불가능한 원시 타입 (다른 값과 중복되지 않는 유일무이한 값)
    • Symbol 함수를 호출해 생성되며, 값은 외부에 노출되지 않음 (var key = Symbol('key');)
    • 프로퍼티 값에 고유한 값을 저장하고 싶을 때 사용될 수 있음
  • undefined 타입 : 변수 선언에 의해 확보된 메모리 공간은 쓰레기 값이 아닌 undefined로 초기화
  • null 타입 : 변수에 값이 없다는 것을 의도적으로 명시 (intentional absence)하기 위해 사용

객체 (Object) : 소프트웨어에서 속성과 기능을 가지는 프로그램의 단위

자바스크립트에서 원시 타입을 제외한 나머지 값들 (객체, 함수, 배열, 정규 표현식)은 객체 타입 (Object Type)이다.

→ 객체 타입은 프로퍼티 및 메소드를 모두 포함하고 있어, 상태와 동작을 하나의 단위로 구조화할 수 있다.

var person = {
  name: 'John', // "name: 'John'"은 프로퍼티, 
  age: 21       // "name"은 프로퍼티 키, "'John'"은 프로퍼티 값
};
  • 객체 타입은 변경 가능한 값 (mutable)
  • 객체 타입을 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 참조 값 (Reference value)에 접근
  • 원시 타입과 다르게, 객체 타입은 여러 개의 식별자들이 하나의 객체를 공유할 수 있음

원시 타입과 객체 타입의 차이점? → 메모리 공간에 저장되는 위치에서 비롯된 차이!

  • 원시 타입 (Primitive) : 값이 스택 영역에 들어감 (Call-By-Value) (cf. 변수의 주소는 별도로 관리됨)
    → (자바스크립트 엔진에 따라) 힙 영역 내의 Symbol Table이나 Constant Pool에 들어갈 수 있음
  • 객체 타입 (Object/Reference) : 값이 힙 영역에 들어감 (Call-By-Reference)

  • 원시 값은 변경 불가능한 값 (immutable)이지만, 객체 값은 변경 가능한 값 (mutable)
  • 원시 값을 변수에 할당하면 변수에는 실제 값이 저장되나, 객체를 변수에 할당하면 변수에는 참조 값이 저장
  • 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달 (Pass-By-Value)되나, 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달 (Pass-By-Reference)

변경 불가능하다는 것은 변수가 아니라 값에 대한 진술!

  • 상수 (재할당이 금지된 변수) != 변경 불가능한 값 (읽기 전용 값)
  • 처음 원시 값을 변수에 할당하면 실제 값이 저장되고, 값을 재할당하면 메모리 공간의 주소가 변경됨

→ 원시 값은 상태 변경을 금지해 불변성 (Immutability)을 보장하여, 데이터의 신뢰성을 보장한다!

그러므로 Call-By-Value 또한 엄격히 표현하면, 변수에 메모리 주소가 전달되는 것을 말한다!

→ 식별자는 메모리에 저장된 값을 식별해야 하므로, 변수와 같은 식별자는 값이 아닌 메모리 주소를 기억한다.

Constant Poll : 스택 영역과 힙 영역 외에 리터럴을 저장하기 위해 자바스크립트 V8 엔진에서 도입

  • Integer가 저장되는 방식?
    • Integer는 기본적으로 스택 영역의 SMI (Small Integer)에 저장
    • 32/64Bit OS에서 32/64Bit를 넘어서면 힙 영역의 Constant Poll에 할당

  • String이 저장되는 방식?
    • String은 문자열으로 취급 → 모든 리터럴은 힙 영역의 Constant Poll에 할당

객체 리터럴에 의한 객체의 생성 : 중괄호 ({}) 내에 0개 이상의 프로퍼티를 정의

  • 변수에 할당되는 시점에 자바스크립트 엔진이 객체 리터럴을 해석하여 객체를 생성
  • 객체 리터럴의 중괄호는 코드 블록을 의미하지 않음 → 중괄호 뒤에 세미콜론을 붙이지 않음
var person = {
  name: 'John',
  sayHello: function() {
    console.log('Hello');
  }
}

프로퍼티 (property) : 객체의 상태를 나타내는 값 (data)

  • 객체는 0개 이상의 프로퍼티의 집합 → 프로퍼티는 키 (key)와 값 (value)으로 구성
    • 자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값이 될 수 있다.
    • 프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심볼 값 ('', "", 식별자)
    • 프로퍼티 값 : 자바스크립트에서 사용할 수 있는 모든 값
var person = {
  name: 'John'
}
  • 마침표 프로퍼티 접근 연산자 .나 대괄호 프로퍼티 접근 연산자 []을 통해 프로퍼티 접근, 생성, 갱신, 삭제
// 프로퍼티 접근
console.log(person.name);
console.log(person[name]);
console.log(person[0]);

// 프로퍼티 갱신
person.name = 'Joo';

// 프로퍼티 동적 생성
person.age = 20;

// 프로퍼티 삭제
delete person.name;
  • ES6 이후부터 객체 리터럴의 확장된 기능을 제공
// 프로퍼티 축약 표현
let name = 'Kim', age = 10;
const person = { name, age };

// 프로퍼티 이름으로 프로퍼티 키를 동적 생성
const prefix = 'person';
let i = 0 ;
const obj = {
  [ ${prefix}-${++i} ] : i,
  [ ${prefix}-${++i} ] : i,
  [ ${prefix}-${++i} ] : i
};

// 메소드 축약 표현
const obj = {
  name: 'Lee',
  func() { console.log(this.name); }
};

자바스크립트 V8 엔진은 자바스크립트 객체의 프로퍼티에 접근하기 위해 동적 탐색 (Dynamic Lookup) 방식 대신, 히든 클래스 (Hidden Class) 방식으로 사용자 편의성과 일정한 성능을 모두 보장하고자 함

메소드 (method) : 프로퍼티를 참조하고 조작할 수 있는 동작 (behavior)

  • 일반 함수와 달리, 메소드는 객체에 묶어 있는 함수를 의미
    • 자바스크립트의 함수는 일급 객체이므로, 값으로 취급할 수 있어 프로퍼티 값으로 사용할 수 있음
var person = {
  name: 'John',
  getName: function() {
    return this.name;
  }
}

태그:

업데이트: