객체 리터럴을 만들고 키를 사용하여 속성 값을 설정 및 액세스하는 등 객체 속성과의 상호작용 대부분은 노출 영역 수준에서 이루어질 가능성이 높습니다. 하지만 객체의 모든 속성을 내부적으로 구성하여 이러한 속성의 액세스, 변경, 정의 방식을 세밀하게 제어할 수 있습니다. 모든 객체 속성에는 '속성 설명어'라고 하는, 해당 속성과 연결된 메타데이터가 포함된 보이지 않는 속성 집합이 있습니다.
속성과 연결된 설명자에는 데이터 설명자와 접근자 설명자의 두 가지 유형이 있습니다. 데이터 설명자에는 속성의 값이 포함된 키 및 값 쌍이 포함되며, 해당 값의 쓰기 가능 여부, 구성 가능 여부, 열거 가능 여부 등이 관계없이 이 값을 포함합니다. 접근자 설명어에는 속성이 설정, 변경 또는 액세스될 때 실행되는 함수가 포함됩니다.
속성 | 설명어 유형 | 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.create
는 Object.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]]