ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 모던 자바스크립트 Deep Dive - 프로퍼티 어트리뷰트
    JavaScript 2021. 9. 16. 19:02

    keyword = [ 내부 슬롯 , 내부 메서드 , 데이터 프로퍼티 , 접근자 프로퍼티 ]

    내부 슬롯내부 메서드는 ECMAScript 사양에서 사용하는 의사 프로퍼티의사 메서드 이다.
    내부 슬롯내부 메서드는 자바스크립트 엔진에서 실제로 동작하지만 개발자가 직접 접근할 수 있도록 외부로 공개된 객체의 프로퍼티는 아니다. 따라서, 자바스크립트 엔진의 내부 로직이므로 직접 접근할 수 없다.

    하지만, 일부 내부 슬롯과 내부 메서드는 접근 수단을 제공 한다.

    예를 들어, 모든 객체는 [[prototype]]이라는 내부 슬롯을 갖는다. 하지만 접근 할 수 없으며, __proto__로 접근할 수 있다.

    const o = {};
    
    o.[[prototype]]  // Syntax Error
    
    o.__proto__  // Object.prototype

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

    프로퍼티 상태 : [값, 갱신 가능 여부, 열거 가능 여부, 재정의 가능 여부]

    [[Value]] , [[Writable]] , [[Enumerable]] , [[Configurable]] 은 직접 접근 할 수 없다.

    따라서, Object.getOwnPropertyDescriptor 메서드를 사용하여 간접적으로 확인할 수 있다.

    cost person = {
        name : 'Kim'
    }
    
    console.log(Object.getOwnPropertyDescriptor(person,'name'));
    // { value : 'Kim', writable : true , enumerable : true , configurable : true }

     

    Object.getOwnPropertyDescriptor는 하나의 프로퍼티에 대한 프로퍼티 디스크립터 객체를 반환하지만,

    ES8 이후 Object.getOwnPropertyDescriptors 메서드는 모든 프로퍼티의 프로퍼티 어트리뷰트정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.

    const o = {
        name : 'Kim',
        age : 25,
    }
    
    console.log(Object.getOwnPropertyDescriptor(o,'name');
    // { value : 'Kim', writable : true , enumerable : true , configurable : true }
    
    console.log(Object.getOwnPropertyDescriptors(o);
    // {
    //     name : { value : 'Kim' , writable : true , enumerable : true , configurable : true },
    //     age : { value : 25 , writable : true , enumerable : true , configurable : true }
    // }

    데이터 프로퍼티 : 키와 값으로 구성된 일반적인 프로퍼티

    접근자 프로퍼티 : 데이터프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티


     

     

    데이터 프로퍼티


    ex) prototype => 데이터 프로퍼티

    [[Value]]

    • 프로퍼티 키를 통해 접근하면 반환되는 값
    • 프로퍼티 키를 통해 값을 변경하면 [[Value]]에 값을 재할당 하는 것

     

    [[Writable]]

    • 프로퍼티 값의 변경 가능 여부
    • [[Writable]] 의 값이 false라면 읽기 전용 프로퍼티가 된다.

     

    [[Enumerable]]

    • 프로퍼티 열거 가능 여부
    • [[Enumerable]] 의 값이 false라면 for ... in 문이나 Object.keys 메서드로 열거할 수 없다.

     

    [[Configurable]]

    • 프로퍼티 재정의 가능 여부
    •  [[Configurable]] 의 값이 false라면 해당 프로퍼티의 삭제 , 변경이 금지된다.

     

     

    접근자 프로퍼티


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

    ex ) __proto__ => 접근자 프로퍼티

     

    [[Get]]

    접근자 프로퍼티 키로 접근하면 데이터 프로퍼티의 값을 읽어들이는 [[Get]] 의 값(getter 함수)가 호출되어 프로퍼티 값을 반환 받는다.

     

    [[Set]]

    접근자 프로퍼티 키로 접근하면 데이터 프로퍼티의 값을 저장하는 [[Set]] 의 값(setter 함수)가 호출되어 프로퍼티 값을 저장한다.

     

    [[Enumerable]]

    데이터 프로퍼티의 Enumerable과 같다.

     

    [[Configurable]]

    데이터 프로퍼티의 Configurable과 같다.

     

    const person = {
        firstName : 'YoungJin',
        lastName : 'Kim'
    
        get fullName(){
            return `${this.firstName} ${this.lastName}`;
        }
        
        set fullName(name){
            [this.firstName, this.lastName] = name.split(' ');
        }
    };
    
    // fullName에 접근하면 getter 함수 호출
    console.log(person.fullName) // YoungJin Kim
    
    // fullName에 값을 저장하면 setter 함수 호출
    person.fullName = 'Jenny Kim'
    
    console.log(person.fullname) // 'Jenny Kim'
    
    let descriptor = Object.getOwnPropertyDescriptor(person,'firstName');
    console.log(descriptor);
    // { value : 'YoungJin' , writable : true , enumerable : true , configurable : true }
    
    descriptor = Object.getOwnpropertyDescriptor(person,'fullName');
    console.log(descriptor);
    // { get : f, set : f, enumerable : true , configurable : true }

     

    person의 firstName과 lastName은 데이터 프로퍼티이고

    person의 fullName은 접근자 프로퍼티이다.

     


    프로퍼티의 어트리뷰트 정의하기


    Object.defineProperty(object,key,addtribute)

    const person = {}
    
    Object.defineProperty(person,'firstName',{
        value : 'YoungJin',
        writable : true,
        enumarable : true,
        configurable : true
    });
    
    Object.defineProperty(person,'fullName',{
        get() {
            return `${this.firstName} ${this.lastName}`
        },
        
        set(name){
            [ this.firstName , this.lastName ] = name.split(' ');
        },
        enumerable : true,
        configurable : true
    });
    
    Object.defineProperty(person,'lastName',{
        value : 'Kim'
    });
    
    let descriptor = Object.getOwnPropertyDescriptor(person,'lastName');
    console.log(descriptor);
    // { value : 'Kim', writable : false, enumerable : false , configurable : false }
    
    console.log(Object.keys(person));  // ["firstName"]
    
    person.lastName = 'Lee'  // X
    
    delete person.lastName  // X

     

     


    객체 변경 금지


     

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

     

    댓글

Designed by Tistory.