main-logo

프로퍼티 어트리뷰트

프로퍼티 와 어트리뷰트에 대해 알아보자

profile
1320129
2023년 10월 19일 · 0 분 소요

들어가며

오늘은 유독 제일 지루한 내용 중에 하나였던 프로퍼티 어 트리뷰트에 대해서 알아보려고 합니다.

해당 내용도 매우 추상적이고 일부분 확인 가능하지만 “그래서 나한테 뭐가 중헌디?” 라는 생각이 많이 들었던 내용입니다.

조금만 참아내고 같이 확인해 볼까요?

 

내부 슬롯 / 내부 메서드

내부 슬롯 / 내부 메서드는 간단히 말하면

프로퍼티로 만들어진 자바스크립트 설명서!

라고 생각합니다.

내부 메서드 : ECMAScript 사양에서 이용하는 의사 메서드입니다.

내부 슬롯 : ECMAScript 사양에서 이용하는 의사 프로퍼티입니다.

의사 메서드?, 의사 프로퍼티?

image1.gif

"의사 메서드(pseudo-method)"와 "의사 프로퍼티(pseudo-property)"는 일반적인 프로그래밍 용어가 아닙니다.

ECMAScript 사양의 "내부 슬롯"과 "내부 메서드"를 설명하는 데 사용된 것으로 보이는데요.

이러한 용어를 사용하는 이유는, 이들이 실제 JavaScript 코드에서 직접 접근하거나 조작할 수 없다는 것을 강조하기 위함입니다.

즉, 이들은 ECMAScript 사양 내에서만 존재하며, 그 사양을 설명하기 위해 만들어진 '가상' 또는 '의사' 개념이라고 볼 수 있습니다.

실제 JavaScript 코드에서 접근 가능한 객체의 속성(property)과 메서드(method)와 달리,

내부 슬롯과 내부 메서드는 코드 실행에 영향을 미치지만 직접 조작하거나 참조할 수 없습니다.

이유는 내부 슬롯과 내부 메서드는 자바스크립트 엔진의 구현 알고리즘을 설명하기 위한 프로퍼티인데요.

따라서 그것들은 '의사' 또는 '가상'의 속성과 메서드라고 볼 수 있으며, 이럴 때 "의사 프로퍼티" 또는 "의사 메서드"라고 부르기도 합니다.

다시한번 말씀 드리지만, 내부슬롯과 내부 메소드는 자바스크립 엔진의 내부로직이므로 개발자가 직접적으로 접근이나 호출이 불가능 한데요.

하지만 일부 내부슬롯과 내부 메소드는 간접적으로 수단을 제공하는데

모두가 잘알고 있는 [[prototype]]에 __proto__ 가 그중 하나입니다.

(하지만 __proto__는 ECMAScript 사양에서는 공식적으로 권장하지 않는 내부 프로퍼티입니다.)

console.log(Array.__proto__ ) //function () { [native code] }

console.log(Array.[[Prototype]] ) //Prototype is not defined

프로퍼티 어트리뷰트

JavaScript에서 객체의 프로퍼티는 값(value) 외에도 몇 가지 속성(attributes) 또는 "디스크립터(descriptor)"를 가질 수 있습니다.

이러한 속성은 프로퍼티가 어떻게 동작하는지를 정의합니다.

또한 데이터 프로퍼티와, 접근자 프로퍼티로 구분할 수 있습니다.

데이터 프로퍼티

데이터 프로퍼티는 가장 일반적인 형태의 객체 속성을 나타내며, 단순한 값을 저장하는 역할을 합니다.

다음 네 가지 어트리뷰트를 포함할 수 있습니다.

1  [[value]]:  프로퍼티의 값입니다.

2. [[writable]]: 프로퍼티가 변경 가능한지 여부를 나타내며, true 또는 false 값을 가집니다.

3. [[enumerable]]: 프로퍼티가 Object.keys() 메서드 등을 통해 열거할 수 있는지 여부를 나타내며, true 또는 false 값을 가집니다.

4. [[configurable]]: 프로퍼티의 디스크립터가 변경 가능한지, 그리고 해당 프로퍼티가 삭제 가능한지 여부를 나타내며, true 또는 false 값을 가집니다.

접근자 프로퍼티

접근자 프로퍼티(Accessor Property)는 특정 객체의 속성에 접근할 때 추가적인 동작을 정의하는 데 사용됩니다.

다음 네 가지 어트리뷰트를 포함할 수 있습니다.

1. [[Get]]: 이 소유자가 값을 읽으려고 할 때 호출되는 함수 (getter)

2. [[Set]]: 이 소유자가 값을 쓸 때 호출되는 함수 (setter)

3. [[Enumerable]]: Object.keys() 등의 메서드에 의해 열거될 수 있는지 여부.

4. [[Configurable]]: 이 소유자가 삭제 가능하거나, 어트리뷰트가 변경 가능한지 여부

 

예제코드를 같이 확인해볼까요?

const student = {
firstName: "John",
lastName: "Doe",

// getter 함수
get fullName() {
return `${this.firstName} ${this.lastName}`;
},

// setter 함수
set fullName(fullName) {
[this.firstName, this.lastName] = fullName.split(' ');
}
};

console.log(student.fullName); // John Doe

student.fullName = "Jane Smith";
console.log(student.fullName); // Jane Smith

descriptor = Object.getOwnPropertyDescriptor(student, 'fullName');
console.log(descriptor);
// {get: f, set: f, enumerable: true, configurable: true}

Getter (Get 함수)
Getter는 객체의 프로퍼티 값을 읽을 때 호출되는 함수입니다.

이 함수는 객체 속성에 접근할 때 추가적인 동작을 정의하고, 값을 반환합니다.

Getter를 사용하여 객체의 특정 속성에 접근할 때 추가적인 로직을 수행할 수 있습니다.

예를 들어, 위의 예제에서 'fullName' 속성의 Getter는 'this.firstName'과 'this.lastName'를 결합하여 전체 이름을 반환합니다.

이를 통해 'student.fullName'을 호출하면 "John Doe" 또는 "Jane Smith"와 같은 값을 반환할 수 있습니다.

 

Setter (Set 함수)
Setter는 객체의 프로퍼티 값을 변경할 때 호출되는 함수입니다.

이 함수는 값을 쓸 때 호출되며, 객체 속성에 새로운 값을 설정하거나 변경할 수 있는 로직을 정의합니다.

Setter를 사용하여 객체의 특정 속성에 값을 설정할 때 추가적인 검증 또는 가공을 수행할 수 있습니다.

예를 들어, 위의 예제에서 'fullName' 속성의 Setter는 입력 문자열을 공백(' ')으로 분리하여 'firstName'과 'lastName' 속성에 할당합니다.

이를 통해 'student.fullName = "Jane Smith"'와 같은 할당 작업을 수행할 때 객체 내부의 다른 속성을 업데이트할 수 있습니다.

또한, 'Object.getOwnPropertyDescriptor()' 메소드를 사용하여 객체 속성의 디스크립터를 확인할 때 'get'과 'set' 함수가 추가된 것을 확인할 수 있습니다.

이러한 디스크립터 정보는 객체 속성에 대한 동작을 정의하고 관리하는 데 도움이 됩니다.

디스크립터가 무엇이냐고요??

디스크립터?

디스크립터는 객체의 프로퍼티에 대한 상세한 정보를 담은 객체입니다

방금 전 예제 코드에서 'Object.getOwnPropertyDescriptor()'로 확인하여 나온

{get: f, set: f, enumerable: true, configurable: true} 해당 부분인 거죠!

fullName이라는 getter, setter 함수가 추가되어 확인되고 있습니다.

객체 변경 방지

JavaScript에서는 객체를 변경하는 것을 방지하기 위한 여러 가지 메소드를 제공합니다. 주요한 메소드들은 다음과 같습니다.

1.Object.preventExtensions(obj):
이 메소드는 객체에 새로운 속성을 추가하는 것을 방지합니다. 이미 존재하는 속성의 값 변경이나 삭제는 가능합니다.

let obj = { prop: 42 };
Object.preventExtensions(obj);
obj.newProp = 33; // 에러, 새로운 속성 추가 불가능
console.log(obj); // { prop: 42 }

Object.seal(obj):
이 메소드는 객체에 새로운 속성을 추가하거나 기존 속성을 삭제하는 것을 방지합니다. 기존의 속성 값은 여전히 변경 가능합니다.

let obj = { prop: 42 };
Object.seal(obj);
delete obj.prop; // 에러, 기존 속성 삭제 불가능
console.log(obj); // { prop: 42 }

Object.freeze(obj):
이 메소드는 객체에 대해 어떠한 변경도 허용하지 않습니다. 즉, 새로운 속성 추가, 기존 속성 삭제, 기존 속성 값 변경 모두 불가능하게 됩니다.

let obj = { prop: 42 };
Object.freeze(obj);
obj.prop = 33; // 에러, 기존 프로퍼티 값 변경 불가능
console.log(obj); // { prop: 42 }

 

마치며

제가 생각했을 때 핵심적인 내용만 추렸는데 양이 많네요.
추상적인 내용이라 까먹을 일이 많을 것 같은데 블로그에 자주 와서 확인해야 할 내용인 것 같습니다.
이외 다른 내용이 좀 더 궁금한다면 추가적인 공부도 좋은 기회일 것 같습니다!
긴 글 읽어주셔서 감사합니다!