ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] 프로퍼티 어트리뷰트, getOwnPropertyDescriptor,defineProperty,getDeepFrozen
    웹/JavaScript 2023. 1. 13. 09:07

    I. 프로퍼티 어트리뷰트 property attributes

    객체의 프로퍼티가 생성될 때 엔진에 의해 자동 정의되는 상태

    💡 프로퍼티에는 두 종류가 있음

    const person = {
    // ⭐️ 1. 데이터 프로퍼티들
    fullName: '홍길동',
    ageInNumber: 25,
    // ⭐️ 2. 접근자 프로퍼티들
    get name () {
    return this.fullName
    .split('')
    .map((letter, idx) => idx === 0 ? letter : '*')
    .join('');
    },
    get age () { return this.ageInNumber + '세'; },
    set age (age) {
    this.ageInNumber = Number(age);
    }
    }
    console.log(
    person.name, person.age
    );

    1. 데이터 프로퍼티의 어트리뷰트

    프로퍼티 어트리뷰트설명설정중 생략시 기본값

    [[Value]] 프로퍼티의 값 undefined
    [[Writable]] 값 갱신 가능 여부 - false일 경우 읽기 전용 false
    [[Enumerable]] 열거(for ... in문, Object.keys 사용) 가능 여부 false
    [[Configurable]] 프로퍼티의 제거, (value와 writable 제외) 어트리뷰트 수정 가능 여부 false



    2. 접근자 프로퍼티의 어트리뷰트

    프로퍼티 어트리뷰트설명설정중 생략시 기본값

    [[Get]] 객체로부터 값을 읽을 때 호출되는 getter 함수 undefined
    [[Set]] 객체에 값을 저장할 때 호출되는 setter 함수 undefined
    [[Enumerable]] 열거(for ... in문, Object.keys 사용) 가능 여부 false
    [[Configurable]] 프로퍼티의 제거, (value와 writable 제외) 어트리뷰트 수정 가능 여부 false




     

    II. Object의 프로퍼티 어트리뷰트 관련 정적 메서드들

    1. getOwnPropertyDescriptor, getOwnPropertyDescriptors

    • 객체 프로퍼티 어트피뷰트들의 설명자 descriptor를 반환
    const person = {
    // ⭐️ 1. 데이터 프로퍼티들
    fullName: '홍길동',
    ageInNumber: 25,
    // ⭐️ 2. 접근자 프로퍼티들
    get name () {
    return this.fullName
    .split('')
    .map((letter, idx) => idx === 0 ? letter : '*')
    .join('');
    },
    get age () { return this.ageInNumber + '세'; },
    set age (age) {
    this.ageInNumber = Number(age);
    }
    }

     

    // 특정 프로퍼티를 지정하여 반환
    console.log('1.',
    Object.getOwnPropertyDescriptor(person, 'fullName')
    );
    console.log('2.',
    Object.getOwnPropertyDescriptor(person, 'ageInNumber')
    );
    console.log('3.', // set: undefined
    Object.getOwnPropertyDescriptor(person, 'name')
    );
    console.log('4.', // get, set 모두 있음
    Object.getOwnPropertyDescriptor(person, 'age')
    );

     

    // 모든 프로퍼티의 어트리뷰트 객체로 묶어 반환
    console.log(
    Object.getOwnPropertyDescriptors(person)
    );



    2. defineProperty, defineProperties

    • 객체의 프로퍼티를 정의
    const person = {};
    // 한 프로퍼티씩 각각 설정
    Object.defineProperty(person, 'fullName', {
    value: '홍길동',
    writable: true
    // 💡 누락한 어트리뷰트는 기본값으로 자동생성
    });
    Object.defineProperty(person, 'name', {
    get () {
    return this.fullName
    .split('')
    .map((letter, idx) => idx === 0 ? letter : '*')
    .join('');
    }
    });
    console.log(person, person.name);
    console.log( // ⚠️ 누락된 어트리뷰트들 확인해볼 것
    Object.getOwnPropertyDescriptors(person)
    );

     

    // 여러 프로퍼티를 객체 형식으로 한꺼번에 설정
    Object.defineProperties(person, {
    ageInNumber: {
    value: 25,
    writable: true
    },
    age: {
    get () { return this.ageInNumber + '세'; },
    set (age) {
    this.ageInNumber = Number(age);
    }
    }
    });
    person.age = 30;
    console.log(person, person.age);
    console.log(
    Object.getOwnPropertyDescriptors(person)
    );




     

    III. 적용예

    const person = {
    fullName: '홍길동',
    ageInNumber: 25,
    };
    // 💡 value를 전우치로 바꾸면
    Object.defineProperty(person, 'fullName', {
    value: '전우치'
    });
    console.log(person);




    console.log(
    Object.keys(person)
    );

     

    // 💡 enumerable을 false로 바꾸면
    Object.defineProperty(person, 'fullName', {
    enumerable: false
    });
    console.log(
    Object.keys(person)
    );

     

    console.log(
    // ⭐️ Object의 또 다른 정적 메서드
    // ⭐️ enemerable이 false인 프로퍼티도 반환
    Object.getOwnPropertyNames(person)
    );




    console.log(
    Object.getOwnPropertyDescriptors(person)
    );

     

    // 💡 seal: configurable을 false로 바꿈
    Object.seal(person);
    console.log(
    Object.getOwnPropertyDescriptors(person)
    );




    console.log(
    Object.getOwnPropertyDescriptors(person)
    );

     

    // 💡 freeze: configurable과 writable을 false로 바꿈
    Object.freeze(person);
    console.log(
    Object.getOwnPropertyDescriptors(person)
    );




     

    IV. 깊은 동결 deep freeze

    • 재귀적으로 객체를 가장 깊숙히까지 동결
    • 🔗 MDN 문서의 deepFreeze 예시와는 달리, 주어진 인자 자체를 변형하지 않도록
    function getDeepFrozen(obj) {
    console.log(obj);
    const result = {};
    const propNames = Object.getOwnPropertyNames(obj);
    for (const name of propNames) {
    const value = obj[name];
    result[name] =
    (value && typeof value === 'object') ?
    getDeepFrozen(value) : value;
    }
    return Object.freeze(result);
    }

     

    let myObj = {
    a: 1,
    b: {
    c: 2,
    d: {
    e: 3,
    f: {
    g: 4
    }
    }
    }
    }

     

    // 여러 번 실행해 볼 것
    myObj.a++;
    myObj.b.c++;
    myObj.b.d.e++;
    myObj.b.d.f.g++;
    console.log(myObj);

     

    // 💡 실행 뒤 바로 위의 출력 코드를 다시 실행해 볼 것
    myObj = getDeepFrozen(myObj);
     
Designed by Tistory.