ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Section 8. 자바스크립트 Object 깊게 다루기 (프로퍼티 어트리뷰트)
    자바스크립트 2023. 4. 6. 10:35

    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
    ); //홍** 25세

     

     

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

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

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

    1. getOwnPropertyDescriptor, getOwnPropertyDescriptors

    객체 프로퍼티 어트리뷰트들의 설명자 descriptor를 반환하는 메서드이다. 

    // 특정 프로퍼티를 지정하여 반환
    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')
    );

    출력문은 다음과 같다

    person 객체의 fullName과 ageInNumber는 데이터 프로퍼티이다. 그리고 기본적으로 이 프로퍼티는 생성했을 시 true라는 것을 볼 수 있다.

    그리고 접근자 프로퍼티도 생성시 기본적으로 true라는 것을 알 수 있고 각각 get과 set이 있는 것을 볼 수 있다. 없을 시에는 undefined이다. 

     

    getOwnPropertyDescriptors는 모든 프로퍼티의 어트리뷰트를 객체로 묶어서 반환한다.

    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)
    );

    출력문은 다음과 같다

    fullName의 writable만 true로 설정이 된 것을 볼 수 있다.

    그리고 나머지 어트리뷰트들이 기본값인 false로 되어 있는 것을 볼 수 있다. 

     

    마찬가지로 여러 프로퍼티를 객체 형식으로 한꺼번에 설정한다면 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)
    );

    이것을 별로 사용할 일은 없겠지만 그래도 간단히 활용하는 것을 예로 들자면 다음과 같다

     

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

    value를 바꿨다. 

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

    enumerable을 false로 바꿨더니 fullName이 나오지 않는 것을 볼 수 있다.

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

    getOwnPropertyNames는 enumerable이 false인 프로퍼티도 반환한다.

     

    또한 앞서 배웠던 seal, freeze를 했을때 어트리뷰트들이 어떻게 변하는지 직접 콘솔창에 출력해보면서 확인하고 넘어가면 좋다.

     

    seal을 하면 configurable이 false로 변한다.

    freeze를 하면 writable이 false로 변하는 것을 알 수 있다.

     

    IV. 깊은 동결 deep freeze

    재귀적으로 객체를 가장 깊숙히까지 동결하는 것을 말한다.

    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);

    여기에 freeze를 쓴다고 해도 a의 값까지만 동결되고 그 안쪽에 있는(눈에 보이는 대로) b나 c의 값들은 변하는 것을 해보지 않아도 알 수 있다. 따라서 반환된 값을 가지고 재귀적으로 호출해서 가장 깊숙한 곳까지 freeze를 해주는 함수를 사용해야 객체의 가장 안쪽의 프로퍼티들까지 freeze가 적용되어 b.d.f.g++이런 연산자를 사용해도 값이 변하지 않는 것을 알 수 있다. 함수는 다음과 같다

    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);
    }
Designed by Tistory.