[딥다이브] 16장 | 프로퍼티 어트리뷰트
내부 슬롯과 내부 메서드
-
의사 프로퍼티와 의사 메서드
-
이중 대솰호 ([[...]])
-
자바스크립트 엔진에서 실제로 동작하지만 개발자가 접근, 호출 불가
- 자바스크립트 엔진 내부 로직임
- 하지만 일부 내부 슬롯과 내부 메서드는 간접적으로 접근할 수 있는 수단 제공
-
모든 객체는 [[Prototype]] 내부 슬롯 가짐
-
proto를 통해 간접적 접근 가능
-
const student = {}; student.[[Prototype]] // SyntaxError student.__proto__ // Object.prototype
-
프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
-
프로퍼티 어트리뷰트: 프로퍼티의 상태를 나타냄
- 프로퍼티의 상태: 프로퍼티의 값, 값의 갱신 가능 여부, 열거 가능 여부, 재정의 가능 여부
- 자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티 어트리뷰트를 기본값으로 자동 정의함
- 자바스크립트 엔진이 관리하는 내부 상태 값인 내부 슬롯
- [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]
-
Object.getOwnPropertyDescriptor 메서드로 간접 확인 가능
const student = { name: 'Dory' } console.log(Object.getOwnPropertyDescriptor(student, 'name')) // {value: "Dory", writable: true, enumerable: true, configurable: true}
- 첫 번째 매개변수: 객체의 참조, 두번째 매개변수: 프로퍼티 키
- 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체 반환
- 존재하지 않는 프로퍼티 || 상속받은 프로퍼티에 대해선 undefined
- 하나의 프로퍼티에 대해 디스크립터 객체 반환
- ES8의 Object.getOwnPropertyDescriptors는 모든 프로퍼티의 프로퍼티 어트리뷰트 제공하는 프로퍼티 디스크립터 객체들 반환
데이터 프로퍼티와 접근자 프로퍼티
- 데이터 프로퍼티 : 키와 값으로 구성된 일반적인 프로퍼티
- 접근자 프로퍼티 : 자체적으로 값을 갖진 X, 다른 데이터 프로퍼티의 값을 읽고 저장할 때 호출되는 접근자 함수로 구성됨
데이터 프로퍼티
- 데이터 프로퍼티의 프로퍼티 어트리뷰트 : 자바스크립트 엔진이 프로퍼티 생성할 때 기본값으로 자동 정의됨
- [[Value]]는 프로퍼티 값, 나머지는 true로 초기화됨
- 프로퍼티 동적 추가해도 위와 마찬가지
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
---|---|---|
[[Value]] | value | 프로퍼티 키를 통해 반환되는 값 프로퍼티 키를 통해 값을 변경하면 [[Value]]에 값을 재할당함 프로퍼티가 없으면 프로퍼티를 동적 생성 & 생성된 프로퍼티의 [[Value]]에 값 저장 |
[[Writable]] | writable | 프로퍼티 값의 변경 여부, 불리언 값 false인 경우 프로퍼티의 [[Value]]의 값은 읽기 전용 프로퍼티가 됨 |
[[Enumerable]] | enumerable | 열거 가능 여부, 불리언 값 false인 경우 for...in, Object.keys 메서드 등으로 열거 불가 |
[[Configurable]] | configurable | 재정의 가능 여부, 불리언 값 false인 경우 삭제, 값 변경이 금지됨 하지만 [[Writable]]이 true인 경우 [[Value]] 변경과 [[Writable]]을 false로 변경하는 것은 허용됨 |
접근자 프로퍼티
- 자체적으로 값 X, 다른 데이터 프로퍼티의 값 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
---|---|---|
[[Get]] | get | 데이터 프로퍼티 값 읽을 때 호출되는 접근자 함수 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 [[Get]]의 값, getter 함수가 호출되고 결과가 프로퍼티 값으로 반환됨 |
[[Set]] | set | 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 접근자 프로퍼티로 값을 저장하면 [[Set]]의 값, setter 함수가 호출되고 그 결과가 프로퍼티 값으로 저장됨 |
[[Enumerable]] | enumerable | 데이터 프로퍼티의 [[Enumerable]]과 같음 |
[[Configurable]] | configurable | 데이터 프로퍼티의 [[Configurable]]과 같음 |
-
접근자 함수 = getter/setter 함수
-
접근자 프로퍼티는 getter와 setter 모두 정의할 수도 있고 하나만 정의할 수도 있음
-
const student = { month: '3'; // month, day는 데이터 프로퍼티 day: '13'; get fullBirthDay() { return `${this.month} ${this.day}`; }, set fullBirthDay() { [this.month, this.day] = name.split(''); } } // 접근자 프로퍼티를 통해 프로퍼티 값 저장 // setter 함수가 호출됨 student.fullBirthDay = '2 15'; // 접근자 프로퍼티를 통해 프로퍼티 값 참조 // getter 함수가 호출됨 console.log(student.fullBirthDay); // 2 15 // fullBirthDay는 접근자 프로퍼티 // get, set, enumerable, configurable을 갖는다 // 프로퍼티 어트리뷰트를 갖는다 descriptor = Object.getOwnPropertyDescriptor(student, 'fullBirthDay'); console.log(descriptor); // {get: f, set: f, enumerable: true, configurable: true}
-
메서드 앞에 get,set이 붙은 것 → getter, setter 함수
- 함수의 이름 fullBirthDay가 접근자 프로퍼티임
- 접근자 프로퍼티는 데이터 프로퍼티 값을 읽기/저장할 때 관여함
-
접근자 프로퍼티로 프로퍼티 값에 접근하는 과정
- 프로퍼티 키 유효한지 확인
- 문자열 || 심벌
- 프로토타입 체인에서 프로퍼티 검색
- 프로퍼티가 데이터인지 접근자인지 확인
- 접근자 프로퍼티의 프로퍼티 어트리뷰트 [[Get]]의 값, getter를 호출해서 그 결과를 반환함.
- Object.getOwnPropertyDescriptor가 반환하는 프로퍼티 디스크립터 객체의 get 프로퍼티 값과 같음
- 프로퍼티 키 유효한지 확인
-
-
접근자 프로퍼티와 데이터 프로퍼티 구별
- getOwnPropertyDescriptor가 반환한 프로퍼티 어트리뷰트 객체를 표현한 프로퍼티 디스크립터 객체가 서로 다름
- 일반 객체의 proto는 접근자, 함수 객체의 prototype은 데이터
프로퍼티 정의
-
새로운 프로퍼티 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의 || 기존 프로퍼티의 프로퍼티 어트리뷰트 재정의
-
객체의 프로퍼티가 어떻게 동작해야 하는지 명확히 정의할 수 있음
-
Object.defineProperty 메서드로 프로퍼티 어트리뷰트 정의
-
인수로 객체의 참조, 데이터 프로퍼티의 키인 문자열, 프로퍼티 디스크립터 객체 전달
-
프로퍼티 디스크립터 객체의 프로퍼티 일부 생략 가능
프로퍼티 디스크립터
객체의 프로퍼티대응하는 프로퍼티
어트리뷰트생략했을 때의
기본값value [[Value]] undefined get [[Get]] undefined set [[Set]] undefined writable [[Writable]] false enumerable [[Enumerable]] false configurable [[Configurable]] false -
Object.defineProperty는 한 번에 하나의 프로퍼티, defineProperties는 여러 개의 프로퍼티 한 번에 정의 가능
-
객체 변경 방지
- 객체는 재할당 없이 직접 변경 가능
- 프로퍼티 추가, 삭제, 갱신, 프로퍼티 어트리뷰트 재정의 가능
- 객체의 변경을 방지하는 다양한 메서드
구분 | 메서드 | 추가 | 삭제 | 값 읽기 | 값 쓰기 | 어트리뷰트 재정의 |
---|---|---|---|---|---|---|
객체 확장 금지 | Object.preventExtensions | X | O | O | O | O |
객체 밀봉 | Object.seal | X | X | O | O | X |
객체 동결 | Object.freeze | X | X | O | X | X |
객체 확장 금지
- 프로퍼티 추가 금지
- 프로퍼티 동적 추가와 Object.defineProperty 둘 다 금지됨
- Object.isExtensible로 확장 가능 여부 확인 가능
객체 밀봉
- 프로퍼티 추가, 삭제, 프로퍼티 어트리뷰트 재정의 금지
- 읽기, 쓰기만 가능
- Object.isSealed로 밀봉 여부 확인 가능
객체 동결
- 읽기만 가능
- Object.isFrozen으로 동결 여부 확인 가능
불변 객체
-
위의 변경 방지 메서드들은 얕은 변경방지
-
직속 프로퍼티만 변경 방지, 중첩 객체까지는 영향 못줌
-
ex. Object.freeze 사용해도 객체 속 객체는 동결할 수 없음
-
const student = { name: 'Dory', major: { college: 'engineering', department: 'computer science' } } Object.freeze(student); student.major.department = 'computer engineering'
-
중첩 객체까지 적용해서 읽기 전용의 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티의 재귀적으로 freeze 호출해야됨,,
-
Author And Source
이 문제에 관하여([딥다이브] 16장 | 프로퍼티 어트리뷰트), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kyaeim/딥다이브-16장-프로퍼티-어트리뷰트저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)