프로퍼티 어트리뷰트 (property attribute)

gyomni·2022년 1월 28일
0

JavaScript

목록 보기
11/14
post-thumbnail

🔎 내부 슬롯(internal slot)과 내부 메서드(internal method)

  • 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티(pseudo property)와 의사 메서드(pseudo method)이다.

  • ECMAscript 사양에 등장하는 이중 대괄호 ([[...]])로 감싼 이름들이 내부 슬롯과 내부 메서드!

  • 자바스크립트 엔진 내부 로직이므로 원칙적으로 자바스크립트는 내부 슬롯과 내부 메서드에 직접적으로 접근하거나 호출하는 방법을 제공하지 않음.
    (단, 일부 내부 슬롯과 내부 메서드에 한해 간접적으로 접근할 수 있는 수단 제공하기는 함.)

    ex) 모든 객체는 [[Prototype]]이라는 내부 슬롯을 갖는다. 내부 슬롯은 js 엔진의 내부 로직이므로 원칙적으로 직접 적근할 수 없지만 [[Prototype]]내부 슬롯의 경우,__proto__를 통해 간접적으로 접근 할 수 있음.

[ 예제 ]

const a={};
a.[[Prototype]] // Uncaught SyntaxError: Unexpected token '['
a.__proto__ // Object.prototype

🔎 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체

자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다.

  • 프로퍼티 상태
    : 프로퍼티 값(value), 값의 갱신 가능 여부(writable), 열거 가능 여부(enumerable), 재정의 가능 여부(configurable)

  • 프로퍼티 어트리뷰트
    : js 엔진이 관리하는 내부 상태 값(meta-property)인 내부 슬롯[[Value]], [[Writable]], [[Enumerable]], ```[Configurable]]````

  • 프로퍼티 어트리뷰트에 직접 접근할 수 없지만, Object.getOwnPropertyDescriptor메서드를 사용하여 간접적으로 확인할 수는 있음.
    -> 사용 : Object.getOwnPropertyDescriptor(객체의 참조, 프로퍼티 키)
    -> Object.getOwnPropertyDescriptor메서드는 프로퍼티 어트리뷰트 정보 제공하는 프로퍼티 디스크립터(Property Descriptor) 객체를 반환.
    -> 존재하지 않는 프로퍼티 or 상속받은 프로퍼티에 대한 디스트립터 요구하면 undefined반환.

  • Object.getOwnPropertyDescriptor 메서드는 하나의 프로퍼티에 대해 프로퍼티 디스크립터 객체 반환하지만, ES8에서 도입된 Object.getOwnPropertyDescriptor 메서드는 모든 프로퍼티의 프로퍼티 어트리뷰트 정보 제공하는 프로퍼티 디스크립터 객체들을 반환함.


🔎 데이터 프로퍼티와 접근자 프로퍼티

프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분!

  • 데이터 프로퍼티(data property)
    : 키와 값으로 구성된 일반적 프로퍼티.
    -> [[Value]], [[Writable]], [[Enumerable]], [Configurable]] 와 같은 프로퍼티 어트리뷰트를 갖는다.

  • 접근자 프로퍼티(accessor property)
    : 자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수(accessor function)로 구성된 프로퍼티.
    -> [[Get]], [[Set]], [[Enumerable]], [Configurable]]와 같은프로퍼티 어트리뷰트를 갖는다.

  • 접근자 프로퍼티, 데이터 프로퍼티 구분.
    -> 일반 객체의 __proto__는 접근자 프로퍼티.

      Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
      // {get: f, set: f, enumerable: false, configurable: false} // 프로퍼티 디스크립터

    -> 함수 객체의 prototype은 데이터 프로퍼티.

       Object.getOwnPropertyDescriptor(function() {}, 'prototype');
      // {value:{...}, writable: true, enumerable: false, configurable: false} // 프로퍼티 디스크립터
    

🔎 프로퍼티 정의

새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것.

  • Object.defineProperty 메서드 사용하면 프로퍼티의 어트리뷰트 정의 할 수 있음.
    -> Object.defineProperty(객체의 참조 데이터, 프로퍼티 키(문자열), 프로퍼티 디스크립터 객체)
    (디스크립터 객체의 프로퍼티를 누락시키면 value,get,set은 undefined이, writable, enumerable, configurable은false가 기본값)

  • Object.defineProperty메서드는 한번에 하나의 프로퍼티만 정의가능.
    But! Object.defineProperties 메서드 사용하면 여러 개의 프로퍼티 한 번에 정의 가능!

🔎 객체 변경 방지

  • 객체는 변경 가능한 값이므로 재할당 없이 직접 변경할 수 있다.
    -> 프로퍼티 추가 or 삭제 가능.
    -> 프로퍼티 값 갱신 가능.
    ->Object.defineProperty or Object.defineProperties 메서드 사용해서 프로퍼티 어트리뷰트를 재정의할 수도 있음.

  • 자바스크립트는 객체 변경을 방시하는 다양한 메서드 제공
    (객체 변경 방지 메서드들은 변경 금지 강도 다름.)

💡 객체 확장 금지

->Object.preventExtensions()
-> 확장이 금지된 객체는 프로퍼티 추가 금지
-> ① 프로퍼티 동적 추가, ② Object.defineProperty메서드로 추가 => 두 가지 방법 모두 금지
-> 확장 가능한 객체인지는 Object.isExtensible 메서드로 확인 가능
-> 추가는 금지되지만, 삭제는 가능

💡 객체 밀봉

->Object.seal()
-> 프로퍼티 추가 및 삭제와 프로퍼티 어트리뷰트 재정의 금지
-> 읽기와 쓰기만 가능
-> 밀봉된 객체인지 여부는 Object.isSealed 메서드로 확인 가능

💡 객체 동결

->Object.freeze()
-> 프로퍼티 추가, 삭제, 프로퍼티 어트리뷰트 재정의 금지, 프로퍼티 값 갱신 금지.
-> 읽기만 가능
-> 동결된 객체인지 여부는 Object.isfrozen()

💡 불변 객체

-> 위의 세가지 변경 방지 메서드들은 얕은 변경 방지(shallow only)로 직속 프로퍼티만 변경 방지되고 중첩 객체까지는 영향 주지 못함

-> 객체의 중첩 객체까지 동결하여 변경 불가능한 읽기 전용 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze메서드 호출해야 함

학습 자료 : 모던 자바스크립트 Deep Dive - 이웅모

profile
Front-end developer 👩‍💻✍

0개의 댓글