참고: https://262.ecma-international.org/6.0/#sec-object-internal-methods-and-internal-slots
프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분할 수 있다.
데이터 프로퍼티
접근자 프로퍼티
- 자체적으로 값을 갖지는 않고 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
- 접근자 함수는 getter/setter 함수라고도 부른다. getter/setter를 모두 정의할 수도 있고 하나만 정의할 수도 있다.
(이미지 출처: https://velog.velcdn.com/images/nikki/post/5686da83-38c4-4cee-9d6f-c5aa94aaf16e/image.png)
get 메서드의 동작 원리(과정)
- 입력받은 프로퍼티의 키가 유효한지 확인한다. 프로퍼티의 키는 문자열 또는 심벌이어야 한다.
- 프로토타입 체인에서 프로퍼티를 검색한다.
- 검색된 프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인한다.
- 접근자 프로퍼티의 프로퍼티 어트리뷰트 [[GET]]의 값, 즉 getter 함수를 호출하여 그 결과를 반환한다.
cf) 프로토타입
프로토타입은 어떤 객체의 상위(부모) 객체의 역할을 하는 객체. 프로토타입은 하위(자식) 객체에게 자신의 프로퍼티와 메서드를 상속한다. 프로토타입 객체의 프로퍼티나 메서드를 상속받은 하위 객체는 자신의 프로퍼티나 메서드인 것처럼 자유롭게 사용할 수 있다. 프로토타입 체인은 프로토타입이 단방향 링크드 리스트 형태로 연결되어 있는 상속 구조를 말한다.
객체는 변경 가능한 값이므로 재할당 없이 직접 변경할 수 있다. Object.defineProperty, Object.defineProperties 메서드로 어트리뷰트를 재정의 할 수도 있다.
자바스크립트는 객체의 변경을 방지하는 다양한 메서드를 제공한다. 객체 변경 방지 메서드들은 객체의 변경을 방지하는 강도가 다르다.
객체 확장 금지
객체 밀봉
객체 동결
불변 객체
function deepFreeze(target) {
// 객체가 아니거나 동결된 객체는 무시하고 객체이고 동결되지 않은 객체만 동결한다.
if(target && typeof target === 'object' && !Object.isFrozen(target)) {
Object.freeze(target);
Object.keys(target).forEach(key => deepFreeze(target[key]));
}
return target;
}
const person = {
name: 'Lee',
address: {city: 'Seoul'}
};
// 깊은 객체 동결
deepFreeze(person);
console.log(Object.isFrozen(person)); // true
console.log(Object.isFrozen(person.address)); // true
person.address.city = 'Busan';
console.log(person); // {name: 'Lee', address: {city: 'Seoul'}}