icon

메티의 블로그

자바스크립트 객체 리터럴
🔤

자바스크립트 객체 리터럴

Tags
JavaScript
날짜
Apr 16, 2024
상태
공개
  • 리터럴이란?
    • 소스코드의 고정된 값을 나타내는 표기법, 예를 들어 ‘5’, ‘”Hello”’, ‘true’ 같은 코드 내에서 일반적으로 우변에 들어가는 실질 값을 말합니다.
 
  • 객체 리터럴?
    • 자바스크립트에서 대부분의 변수는 객체로 정의하게 됩니다. 그래서 편의성을 위해 리터럴을 통한 생성를 지원합니다. 객체를 생성해 변수에 대입하는 방법은 객체 리터럴 이외에도 다양하게 많습니다. (생성자 함수나 팩토리 함수 등)
      let person = { name: "John", age: 30, greet: function() { console.log("Hello, " + this.name); } }; person.age // 30 person.greet(); // "Hello, John" delete person.name; // { age: 30, greet: function }
      일반적인 사용법
      {} 표기가 객체 리터럴에서 한 객체를 알리는 표현이며, 한 객체는 여러개의 프로퍼티를 가질 수 있습니다. 프로퍼티는 key 와 value 쌍을 가지며 표현은 key: value 로 하게 됩니다. key 는 문자형이나 심볼형만 사용할 수 있으며, value 는 원시형 값과 객체등 거의 모든 자료형이 허용됩니다.
       
      객체 리터럴 ES6 확장
      let x = 1, y = 2; const obj = { x, y }; console.log(obj); // {x: 1, y: 2}
      리터럴 선언 시 변수명과 그 값이 같으면 다음과 같이 축약 가능
      // ES6 const prefix = 'prop'; let i = 0; // 객체 리터럴 내부에서 계산된 프로퍼티 이름으로 프로퍼티 키를 동적 생성 const obj = { [`${prefix}-${++i}`]: i, [`${prefix}-${++i}`]: i, [`${prefix}-${++i}`]: i, }; console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3}
      객체 리터럴 내부에서 계산된 프로퍼티 이름으로 동적 생성 가능
      const obj = { name: 'Lee', sayHi() { console.log('Hi! ' + this.name); } }; obj.sayHi(); // Hi! Lee
      함수 또한 축약 가능
      const obj = { name: 'Lee', sayHi() { console.log('Hi! ' + this.name); } }; const obj2 = { ...obj, name: 'Hong' } obj.sayHi(); // Hi! Hong
      spread 연산자를 활용한 프로퍼티 복사
       
  • V8 엔진은 자바스크립트 객체 리터럴을 어떻게 해석하고 내부적으로 저장할까요?
    • 클래스 기반 객체지향언어에서의 객체 선언 및 메모리 관리
      • 자바나 C++ 같은 클래스 기반 객체 지향 언어는 이미 프로퍼티와 메소드가 지정되어있어서, 메모리에 얼마나 많은 공간이 필요한지 바로 알 수 있습니다. 그래서 새 객체를 만들 때 메모리를 어떻게 확보할지에 대한 로직이 간단합니다.
       
    • 자바스크립트 객체 선언 및 메모리 관리
      • 하지만 자바스크립트 객체는 동적으로 생성되며, 프로퍼티가 추가 삭제 될 수 있고, 순서 또한 보장되지 않습니다. 그래서 v8 엔진은 객체 프로퍼티 key와 value 관련한 해시 테이블을 두고 접근합니다. 하지만, 이는 성능적으로 좋지 않습니다. v8 은 여기서 성능을 위한 히든 클래스라는 개념을 캐싱 매커니즘으로 사용하고 있습니다.
         
    • 히든 클래스
      • 히든 클래스는 프로퍼티가 바뀔 때, 각각 그 객체에 대한 클래스를 만들어 놓는다고 생각하면 쉽습니다. 히든 클래스는 객체와 매핑이 되며, 이를 통해 메모리에 어떻게 올라가게 될 지 빠르게 예측할 수 있습니다. 여느 캐시가 그렇듯이 캐시가 없을 때의 첫 연산은 무겁지만, 그 이후 다시 접근 할 때는 더 빠르게 접근 할 수 있습니다. 이렇게 만들어 놓은 히든 클래스들 덕분에 선언된 프로퍼티가 비슷한 객체들은 관련 히든 클래스 덕분에 프로퍼티 접근 속도가 빨라질 수 있습니다. (이때, 히든 클래스는 프로퍼티의 value 값이 변경된다고 새로 생성 되는 것은 아닙니다.)
        또한, 객체의 프로퍼티 순서가 다르면 다른 히든 클래스를 가지게 됩니다.
        // 두 객체가 가지는 히든 클래스는 다릅니다. const obj1 = { a: 1, b: 2 }; const obj2 = { b: 2, a: 1 };
         
    • 그래서 우리가 객체를 리터럴로 선언을 할 때 유의해야 할 점은?
        1. 객체 프로퍼티를 동적으로 변경하는 것은 무거운 연산인 편입니다.
          1. 히든 클래스는 객체의 프로퍼티가 추가, 삭제 될 때 새로 생깁니다. 이 히든 클래스 생성은 오버헤드가 되기 때문에, 동적 수정 (delete 연산이나 한 객체에서 프로퍼티를 새로 추가 하는 것)은 상대적으로 무거운 연산이 되게 됩니다.
        1. 객체 리터럴로 선언 할 때, 같은 프로퍼티를 가지는 객체가 많다면, 그 프로퍼티의 순서가 중요합니다.
          1. 프로퍼티가 유사한 객체들은 프로퍼티의 순서를 맞추어 선언하면 성능적으로 도움이 됩니다.
        1. 객체 리터럴로 선언 할 때, 빈 값으로 선언 했다가 변경하는 것 보다, 그 프로퍼티들을 미리 선언해주는 것이 좋습니다.
          1. 1번의 이유와 같은 이유로 객체 프로퍼티가 동적으로 변경되는 행위이기 때문입니다. 빈 객체 선언은 대부분의 경우에 성능에 좋을 일이 없겠네요.
             
 

연관 포스트