관리 메뉴

흰둥씨의 개발장

[자바스크립트] 딥다이브) property attribute 본문

BoOk/JS deep dive

[자바스크립트] 딥다이브) property attribute

돈워리비해삐 2023. 6. 23. 21:02

1) 내부 슬롯(internal slot)과 내부 메서드 (internal method)

자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAscript사양에서 사용하는 pseudo property와 pseudo method

const myObject = {};

myObject.[[property]]//SyntaxError; 내부 슬롯은 자바스크립트 엔진의 내부로직으로 직접접근불가
myObject.__proto__  // Object.prototype ; 일부 내부슬롯, 내부메서드 한하여 간접접근가능

 

2) 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체

ㄴ자바스크립트 엔진은 프로퍼티 생성할때 프로퍼티 상태를 나타내는 속성을 기본값으로 자동정의함
프로퍼티 상태 ?  프로퍼티의 값(value), 값갱신가능여부, 열거가능여부, 재정의 가능여부
프로퍼티 속성 ? 자바스크립트 엔진이 관리하는 내부상태 값인 내부 슬롯 [[value]], [Writable]], [[Enumerable]], [[Configurable]]
ㄴ프로퍼티 속성에 직접 접근 할수 없으나 Object.getOwnPropertyDescriptor메서드로 간접 확인은 가능 

const p = { name : "kim" }

p.age = 20;  //동적생성

console.log(Object.getOwnPropertyDescriptors(p)); /* {name: {…}, age: {…}} */

ㄴobject.getOwnPropertyDescriptor(객체의 참조, "프로퍼티 키")  => 프로퍼티 디스크립터 객체 반환

 

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

프로퍼티 - 데이터 프로퍼티 : 키와 값으로 구성된 일반적인 프로퍼티 (프로퍼티 속성가짐)
                ㄴ[[value]], [[Writable]], [[Enumerable]], [[Configurable]]
              - 접근자 프로퍼티 : 자체적으로 값을 갖지않음,  다른 데이터 프로퍼티 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성
                ㄴ[[Get]], [[Set]], [[Enumerable]], [[Configurable]]

** 프로토 타입 : 어떤 객체의 상위 객체 역할을 하는 객체  (하위에게 자신의 프로퍼티, 메소드를 상속함. 상속받으면 자기꺼처럼 쓸수 있음)

4) 프로퍼티 정의

ㄴ프로퍼티 정의 ? 새로운 프로퍼티를 추가하면서, 프로퍼티 속성을 명시적으로 정의하거나, 기존 프로퍼티 속성을 재정의하는 것 

데이터 프로퍼티 

const sival = {};

Object.defineProperty(sival, 'firstName', { //데이터 프로퍼티 정의
	value :'leesaengmang',
    writable: true,
    enumerable: true, 
    configurable: true,
    });
    
Object.defineProperty(sival, 'lastName', { //데이터 프로퍼티 정의
	value :'Zanggu'
    });

let descriptor = Object.getOwnPropertyDescriptor(sival, 'firstName');
console.log('firstName', descriptor);
//firstName {value: 'leesaengmang', writable: true, enumerable: true, configurable: true}

descriptor = Object.getOwnPropertyDescriptor(sival, 'lastName');
console.log('lastName', descriptor);//디스크립터 객체 프로퍼티 누락하면 undefined와 false가 기본값
//lastName {value: 'Zanggu', writable: false, enumerable: false, configurable: false}

console.log(Object.keys(sival)); // ['firstName'] 라스트네임은 enumerable이 false라 안뜸 

sival.lastName = 'bal'; // 무시됨 . writable의 값이 false이면 해당프로퍼티의 value값 변경불가 

delete.sival.lastName;  // 무시됨 . configurable 값이 false면 해당 프로퍼티 삭제 불가



///////////////////////
//접근자 프로퍼티

Object.defineProperty(sival, 'fullName', {
	get(){ 
    	return `${this.firstName} ${this.lastName}`;
        },
    set(name) {
    	[this.firstName, this.lastName] = name.split(' ');
        },
        enumerable : true, 
        configurable : true, 
      });
      
descriptor = Object.getOwnPropertyDescriptor(sival, 'fullName');
console.log('fullName', descriptor);
//fullName {enumerable: true, configurable: true, get: ƒ, set: ƒ}

sival.fullName = 'a b';  
console.log(sival);
//{firstName: 'a', lastName: 'Zanggu'}

ㄴ 맨 마지막 console.log 출력값이 책에서는  {firstName: 'a', lastName: 'b'}인데
ㄴ 나는 안바뀜... lastName은 어트리뷰트 true로 firstName처럼 추가해서 다시 실행하니까 되긴함 (책의 오류인가봄...ㅎㅎ)

 

 

5) 객체 변경 방지

구분 메서드 프로퍼티
추가
프로퍼티
삭제
프로퍼티 값
읽기
프로퍼티 값
쓰기
프로퍼티
속성 재정의
객체 확장 금지 Object.preventExtensions x O O O O
객체 밀봉 Object.seal x x O O x
객체 동결 Object.freeze x x O x x

 

  - 1)객체 확장 금지 (Object.preventExtensions)
ㄴ확장이 금지된 객체는 프로퍼티 추가가 금지됨 (동적추가, defineProperty로 추가하는 방법 모두 금지됨)
ㄴ확장 가능한 객체인지는 Object.isExtensible로 확인가능

  - 2) 객체 밀봉 (Object.seal)
ㄴ밀봉된 객체는 프로퍼티 추가, 삭제, 속성 재정의금지되고 읽기 쓰기만 가능
ㄴ밀봉된 객체인지 여부는 Object.isSealed로 확인가능 

  - 3) 객체 동결 (Object.freeze)
ㄴ동결된 객체는 프로퍼티 추가, 삭제, 속성 재정의, 값 갱신 금지되고 읽기만 가능 

  - 4) 불변 객체
ㄴ1, 2, 3번의 변경 방지 메서드들은 얕은 변경방지로 직속 프로퍼티만 변경이 방지되고, 중첩 객체까지는 영향 못줌
ㄴ중첩 객체까지 동결하고 싶으면 Object.freeze를 재귀호출해야함