속성 설명어

객체 리터럴을 만들고 키를 사용하여 속성 값을 설정 및 액세스하는 등 객체 속성과의 상호작용 대부분은 노출 영역 수준에서 이루어질 가능성이 높습니다. 하지만 객체의 모든 속성을 내부적으로 구성하여 이러한 속성의 액세스, 변경, 정의 방식을 세밀하게 제어할 수 있습니다. 모든 객체 속성에는 '속성 설명어'라고 하는, 해당 속성과 연결된 메타데이터가 포함된 보이지 않는 속성 집합이 있습니다.

속성과 연결된 설명자에는 데이터 설명자접근자 설명자의 두 가지 유형이 있습니다. 데이터 설명자에는 속성의 값이 포함된 키 및 값 쌍이 포함되며, 해당 값의 쓰기 가능 여부, 구성 가능 여부, 열거 가능 여부 등이 관계없이 이 값을 포함합니다. 접근자 설명어에는 속성이 설정, 변경 또는 액세스될 때 실행되는 함수가 포함됩니다.

속성 설명어 유형
Object.defineProperty()의 기본값
설명
[[Value]] 데이터 undefined 속성 값을 포함합니다.
[[Writable]] 데이터 false 속성의 값을 변경할 수 있는지 여부를 결정합니다.
[[Get]] 접근자 undefined 속성에 액세스할 때 실행되는 속성의 getter 함수입니다.
[[Set]] 접근자 undefined 속성이 설정되거나 변경될 때 실행되는 속성의 setter 함수.
[[Configurable]] 둘 다 false false인 경우 속성을 삭제할 수 없으며 속성을 변경할 수도 없습니다. 이 값이 false이고 [[Writable]]true이면 속성 값은 계속 변경할 수 있습니다.
[[Enumerable]] 둘 다 false true인 경우 for...in 루프 또는 Object.keys() 정적 메서드를 사용하여 속성을 반복할 수 있습니다.

이러한 각 속성은 [[Prototype]]와 동일한 약칭을 사용하며, 이는 이러한 속성에 직접 액세스할 수 없음을 나타냅니다. 대신 Object.defineProperty() 정적 메서드를 사용하여 객체의 속성을 정의하거나 수정하세요. Object.defineProperty()는 작업을 처리할 객체, 만들거나 수정할 속성 키, 생성 또는 수정 중인 속성과 연결된 설명자를 포함하는 객체, 이렇게 세 가지 인수를 허용합니다.

기본적으로 Object.defineProperty()를 사용하여 만든 속성은 쓰기 가능, 열거 가능 또는 구성 불가합니다. 그러나 객체 리터럴의 일부로 또는 점이나 대괄호 표기법을 사용하여 만든 모든 속성은 쓰기, 열거 및 구성 가능합니다.

const myObj = {};

Object.defineProperty(myObj, 'myProperty', {
  value: true,
  writable: false
});

myObj.myProperty;
> true

myObj.myProperty = false;

myObj.myProperty;
> true

예를 들어 [[Writable]]false 값이 있을 때 연결된 속성의 새 값을 설정하려고 하면 엄격 모드에서 자동으로 실패하고 엄격 모드에서는 오류가 발생합니다.

{
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}
> true

(function () {
    "use strict";
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only

설명어를 효과적으로 사용하는 것은 상당히 고급 개념이지만 객체의 내부 구조를 이해하는 것은 보다 일반적인 방식으로 객체 작업과 관련된 구문을 이해하는 데 필수적입니다. 예를 들어 Object.create() 정적 메서드를 사용하면 이러한 개념이 적용됩니다. 이 메서드를 사용하면 새 객체에 연결된 모든 프로토타입을 세부적으로 제어할 수 있습니다.

Object.create()는 기존 객체를 프로토타입으로 사용하여 새 객체를 만듭니다. 이렇게 하면 객체가 자바스크립트의 기본 제공 Object 프로토타입에서 속성을 상속하는 것과 동일한 방식으로 새 객체가 다른 사용자 정의 객체의 속성과 메서드를 상속할 수 있습니다. 객체를 인수로 사용하여 Object.create()를 호출하면 전달된 객체가 프로토타입으로 있는 빈 객체가 생성됩니다.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const newObject = Object.create( myCustomPrototype );

newObject;
> Object {  }
<prototype>: Object { myInheritedProp: 10 }
  myInheritedProp: 10
  <prototype>: Object { … }

Object.createObject.defineProperty()와 유사한 구문을 사용하여 새로 생성된 객체의 자체 속성을 지정하는 두 번째 인수를 가져올 수 있습니다. 즉, 객체를 설명어 속성 집합에 매핑할 수 있습니다.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const myObj = Object.create( myCustomPrototype, {
        myProperty: {
            value: "The new property value.",
            writable: true,
            configurable: true
        }
  });

myObj;
> Object { … }
    myProperty: "The new property value."
    <prototype>: Object { myInheritedProp: 10 }

이 예에서 새 객체 (myObj)는 객체 리터럴(myCustomPrototype)을 프로토타입으로 사용하며, 이 객체에는 상속된 Object.prototype가 포함되어 있어 프로토타입 체인이라는 일련의 상속된 프로토타입이 생성됩니다. 각 객체에는 할당 또는 상속 여부와 관계없이 고유한 할당 또는 상속된 프로토타입이 있는 프로토타입이 있습니다. 이 체인은 자체 프로토타입이 없는 null 프로토타입에서 끝납니다.

const myPrototype = {
  'protoProp': 10
};

const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );

newObject;
> Object { objProp: true }
    objProp: true
    <prototype>: Object { protoProp: 10 }
        protoProp: 10
        <prototype>: Object { … }

값의 프로토타입에 포함된 속성은 프로토타입 속성에 직접 액세스할 필요 없이 객체의 '최상위 수준'에서 사용할 수 있습니다.

const objectLiteral = {
    "value" : true
};

objectLiteral;
> Object { value: true }
    value: true
    <prototype>: Object { … }

objectLiteral.toString();
"[object Object]"

이 패턴은 객체와 연결된 전체 프로토타입 체인에 적용됩니다. 속성에 액세스하려고 할 때 인터프리터는 속성을 찾거나 체인이 끝날 때까지 프로토타입 체인의 각 '수준'에서 속성을 찾습니다.

const myCustomPrototype = {
  'protoProp': "Prototype property value."
};

const myObj = Object.create( myCustomPrototype, {
    myProperty: {
        value: "Top-level property value.",
        writable: true,
        configurable: true
    }
});

myObj.protoProp;
> "Prototype property value."

이해도 테스트

어떤 설명자가 접근자인가요?

[[Get]]
[[Set]]
[[Writable]]