모던자바스크립트 DeepDive : 16장 프로퍼티 어트리뷰트

te-ing·2022년 4월 22일
0
post-thumbnail

자바스크립트의 객체는 키(key)와 값(value)로 구성된 프로퍼티(Property)들의 집합이다.
프로퍼티는 키와 값으로 구성된 일반적인 프로퍼티인 데이터 프로퍼티와, 값을 갖고 있지 않지만 다른 데이터의 프로퍼티의 값을 읽거나 저장하는 접근자 함수로 구성된 접근자 프로퍼티가 있다.

내부 슬롯과 내부 메서드

ECMAScript 사양에 등장하는 이중 대괄호[[...]]로 감싼 이름들이 내부 슬롯과 내부 메서드이며,
자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드이다.

하지만 개발자가 직접 접근할 수있도록 외부로 공개된 객체의 프로퍼티는 아니며, [[Prototype]] __proto__ 와 같이 일부 내부 슬롯과 메서드에 한하여 간접적으로 접근할 수 있다.


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

자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의하는데, 프로퍼티 어트리뷰트는 내부 슬롯(Value,Writable,Enumerable,Configurable)으로, 프로퍼티 어트리뷰트 정보를 제공하는 PropertyDescriptor 객체를 반환하는 Object.getOwnPropertyDescriptor 메서드로 확인할 수 있다.


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

const person = { // 프로퍼티 생성 시 프로퍼티 어트리뷰트 자동 정의
	firstName: 'TaeJung',
	lastName: 'Kim',
	get fullName() { // getter 함수
		return `${this.firstName} ${this.lastName}`;
	},
	set fullName(name) { // setter 함수
		[this.firstName, this.lastName] = name.split(' ');
	}
};
person.fullName = 'Ungmo Lee'; // 접근자 프로퍼티 fullName에 값을 저장하여 setter 함수 호출
console.log(person); // {firstName: "Ungmo", lastName: "Lee"
console.log(person.fullName); // Ungmo Lee 접근자 프로퍼티 fullName으로 getter합수 호출

프로퍼티는 키와 값으로 구성된 일반적인 프로퍼티인 데이터 프로퍼티와, 값을 갖고 있지 않지만 다른 데이터의 프로퍼티의 값을 읽거나 저장하는 접근자 함수로 구성된 접근자 프로퍼티가 있다. 접근자 함수는 getter/setter 함수라고도 부른다.


프로퍼티 정의

const person = {};
Object.defineProperty(person, 'fistName', { // 데이터 프로퍼티 정의
	value: 'Taejung', // 프로퍼티 키를 통해 값에 접근하면 반환되는 값
	writable: true, // 프로퍼티 값의 변경 가능 여부
	enumerable: true, // 열거 가능여부(for ... in, Object.keys 등)
	configurable: true // 프로퍼티 재정의 가능 여부(false인 경우 프로퍼티 삭제,변경 불가)
});
let decriptor = Object.getOwnPropertyDescriptor(person, 'furstName');
console.log('firstName', descriptor); // firstName {value: "Taejung", writable: true,
																			// enumerable: true,	configurable: true}
person.lastName = 'Kim';
Object.defineProperty(person, 'fullName', { // 접근자 프로퍼티 정의
	get() {
		return `${this.firstName} ${this.lastName}`;
	},
	set(name) { // setter 함수
		[this.firstName, this.lastName] = name.split(' ');
	}
};
person.fullName = 'Ungmo Lee'; // 접근자 프로퍼티 fullName에 값을 저장하여 setter 함수 호출
console.log(person); // {firstName: "Ungmo", lastName: "Lee"

객체 변경 방지

구분메서드프로퍼티 추가프로퍼티 삭제프로퍼티 값 읽기프로퍼티 값 쓰기프로퍼티 어트리뷰트 재정의
객체 확장 금지Object.PreventExtensionsXOOOO
객체 밀봉Object.sealXXOOX
객체 동결Object.freezeXXOXX

자바스크립트는 객체의 변경을 막는 다양한 메서드를 제공하는데, 각 메서드마다 객체의 변경을 금지하는 강도가 다르다. 객체 확장금지는 확장만 금지, 객체 밀봉은 읽기와 쓰기만 가능, 객체 동결은 읽기 전용으로 프로퍼티 어트리뷰트를 재정의한다.

function deepFreeze(target) {
	if(target && typeof target === 'object' && !Objet.isFrozen(target)) {
		Object.freeze(target);
		Object.Kets(target).forEach(key => deepFreeze(target[key]));
	}
	return target;
}

앞서 소개한 메서드들은 얕은 변경 방지로, 직속 프로퍼티만 동결되기 때문에 불변 객체를 만들기 위해서는 위처럼 모든 프로퍼티에 대해 재귀적으로 Object.freeze메서드를 호출해야 한다.

profile
병아리 프론트엔드 개발자🐣

0개의 댓글