프로퍼티 어트리뷰트

박재성·2022년 1월 10일
0

프로퍼티 어트리뷰트를 직역하면 '재산 속성'이다.

자바스크립트는 객체로 이뤄졌고, '프로퍼티'는 객체 내부의 어떤 값을 의미한다.

객체 내부의 값을 재산이라고 생각한건 아닐까...

내부 슬롯과 내부 매서드

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

실제 자바스크립트 엔진에서 동작하지만, 개발자가 직접 접근하지 못하도록 설계되어 있다. 경우에 따라 간접적으로 접근할 수 있는 수단을 제공하기는 한다.

프로퍼티 어트리뷰트

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

프로퍼티 상태값은,

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

를 말한다.

프로퍼티 어트리뷰트는 자바스크립트 엔진이 관리하는 내부 상태 값인 내부 슬롯 [[Value]], [[Writable]], [[Enumerable]], [[Configuration]]으로 구성되어 있다.

따라서 프로퍼티 어트리뷰트에 직접 접근은 불가능 하지만 특정 매서드를 사용해 간접적으로 접근할 수 있다.

const person = {
	name: 'Lee'
}
console.log(Object.getOwnPropertyDescriptor(person, 'name'))
// {value: 'Lee', writable: true, enumerable: true, configuaration: true}

프로퍼티

데이터 프로퍼티

키와 값으로 구성된 프로퍼티

데이터 프로퍼티의 어트리뷰트는 'true'로 초기화 된다.

왜냐하면,

value: 프로퍼티 키를 통해 프로퍼티 값에 접근해서 값을 변경하면 재할당이 일어난다. 이때 [[Value]]에 값을 저장

Writable: 값의 변경 여부를 나타내는 값으로, 객체는 변경 가능한 데이터이기 때문에 true로 초기화 된다.

Enumerable: 객체 내부의 값은 이터러블이므로 열거 가 가능하다.

Configuaration: 프로퍼티의 재정의 여부를 나타내는 값으로, 프로퍼티의 삭제가 가능하고, 변경이 가능하므로 true로 초기화 된다.

따라서 데이터 프로퍼티의 어트리뷰트는 true로 초기화 된다.

접근자 프로퍼티

접근자 프로퍼티는 자제적인 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티이다.

set 과 get

'set' 은 데이터 프로퍼티의 값을 저장할 때 호출하는 접근자 함수

'get' 은 데이터 프로퍼티 값을 읽을 때 호출하는 접근자 함수

이를 접근자 함수 'setter', 'getter' 함수라고도 부릅니다.

const person = {
	firstName: 'jaeseong',
    lastName: 'park',
    
    get fullName(){
    	return `${this.firstName} ${this.lastName}`
    },
    
    set fullName(name){
    	[this.firstName, this.lastName] = name.split(' ')
    }
}

console.log(person.firstName + ' ' + person.lastName)

person.fullName('jae park') //setter
console.log(person)

console.log(person.fullName) // getter

프로퍼티 정의

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

const person = {
	Object.defineProperty(person, 'firstName', {
    	value: 'jaeseong',
        writable: true,
        enumerable: ture,
        configurable: true
    });
    
    Object.defineProperty(person, 'lastName', {
    	value: 'Lee'
    })
}

Object.defineProperty(person, 'fullName', {
	get(){ // getter
    	return ~~~~~;
    },
    set(name){  // setter
    	[this.firstName, this.lastName] = name.split(' '),
        enumerable: true,
        configurable: true
    }
})

프로퍼티를 왜 새롭게 정의할까?

정확한 이유는 아니다. 내 나름대로 고민하고 생각한 이유입니다.

자바스크립트에는 원시 타입과 객체 타입이 존재하는데, 원시타입은 값의 변경이 불가능 하지만 객체 타입변경 가능한 값 이다.

따라서 객체 타입은 의도치 않게 값이 변경될 수 있다는 것을 의미한다.

이를 방지하고자 객체의 변경을 방지하도록 하고자, 어트리뷰트에 간접적으로 접근해 'false'로 설정할 수 있다고 생각한다.

이를 매서드 로 제공하고 있다.

  • Object.preventExtension
  • Object.seal
  • Object.freeze

첫 번째는 객체 확장 금지로 프로퍼티의 추가가 금지된다.

두 번째는 객체 밀봉으로 프로퍼티의 삭제 및 추가와 프로퍼티 어트리뷰트 재정의를 금지한다. 즉, 읽기와 쓰기만 가능하다.

셋 째는 객체 동결로 읽기만 가능하고 다른 프로퍼티 상태 값을 false로 할당한다.

한 가지 주의할 점이 있다. 위 매서드는 상속이 불가능 하다.

다른 말로 하면, 중첩 객체까지 영향을 주지 못한다.

const person = {
	name: 'Lee',
    address: {
    	city: 'seoul'
    }
}

Object.freeze(person)
person.address.city = 'busan'
console.log(person) // 1번

person 객체의 'name'을 key로 가지는 프로퍼티는 읽기만 가능하고, address 객체의 프로퍼티 어트리뷰트는 전부 true로 초기화 된 상태이다.

따라서 1번 코드의 결과는 {name: 'Lee', address: {city: 'busan'}} 이 출력된다.

결론

프로퍼티는 자바스크립트를 쓰면서 언제나 마주칠 개념이다.

객체와 프로퍼티는 필요충분조건이라고 생각할 수 있다.

왜 프로퍼티 어트리뷰트 접근이 가능하게 자바스크립트를 설계했는지, 어떤 부분에서 사용이 될지 좀 더 고민해봐야 할 것이다.

profile
개발, 정복

0개의 댓글