프로퍼티 어트리뷰트

ME2DESIGNER.COM·2022년 4월 19일
0

JavaScript

목록 보기
9/16
post-thumbnail

프로퍼티란?

  • 프로퍼티는 프로퍼티 key(이름)와 프로퍼티 value으로 구성된다.
    (Property = key: value)
  • 프로퍼티 key는 프로퍼티를 식별하기 위한 식별자(identifier)다.
  • 아래 Object의 key는 name, value는 ellie 또 다른 key는 age, value는 4 이다.
const ellie = { name: "ellie", age: 4 };

자세한 내용 : https://velog.io/@me2designer/Object#프로퍼티




프로퍼티 어트리뷰트

https://www.youtube.com/watch?v=fFs2pkpWwQU

자바스크립트 엔진은 프로퍼티를 생성할 때, 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다. 프로퍼티의 상태란 프로퍼티의 값(value), 값의 갱신 가능 여부(writable), 열거 가능 여부(enumerable), 재정의 가능 여부(configurable)를 말한다.

프로퍼티 어트리뷰트는 자바스크립트 엔진이 관리하는 내부 상태 값인 내부 슬롯이므로 직접 접근할 수 없지만, Object.getOwnPropertyDescriptor 메소드를 사용하여 간접적으로 확인할 수 있다.




프로퍼티 디스크립터 메소드

  • 첫번째 매개변수에 참조를 전달
  • 두번째 매개변수에 프로퍼티 키를 문자열로 전달하면,
  • 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환한다.
  • 존재 하지 않는 프로퍼티를 상속받으면 undefined가 반환된다.
const person = {
  name: "Lee",
};

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

console.log(Object.getOwnPropertyDescriptor(person, "age"));
// undefined

Object.getOwnPropertyDescriptors

Object.getOwnPropertyDescriptor 메소드는 단 한개의 프로퍼티에 대해 프로퍼티 디스크립터 객체를 반환하지만, Object.getOwnPropertyDescriptors 메소드는 ES8에서 도입된 것으로 모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.

const person = {
  name: "Lee",
  age: "20",
};

console.log(Object.getOwnPropertyDescriptors(person));
/*
{
  age: {value: '20', writable: true, enumerable: true, configurable: true}
  name: {value: 'Lee', writable: true, enumerable: true, configurable: true}
}
*/



프로퍼티 구분

프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분할 수 있다.


데이터 프로퍼티

https://www.youtube.com/watch?v=0AjTZG6bGq8

데이터 프로퍼티(data property)는 키(key)와 값(value)으로 구성된 일반적인 프로퍼티로, 지금까지 살펴본 모든 프로퍼티가 데이터 프로퍼티 이다.

프로퍼티설명
value프로퍼티 키로 프로퍼티 값에 접근하면 반환되는 값
writable프로퍼티 값의 변경 가능 여부를 나타내는 불리언 값
enumerable프로퍼티의 열거 가능 여부를 나타내는 불리언 값
configurable프로퍼티의 재정의 가능 여부를 나타내는 불리언 값

접근자 프로퍼티

https://www.youtube.com/watch?v=JIMUy2RmclI

접근자 프로퍼티(accessor property)는 자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수(accessor function)로 구성된 프로퍼티 이다.

프로퍼티설명
get프로퍼티 를 읽을 때 동작되는 함수
set프로퍼티 값을 쓸 때 동작되는 함수
enumerable데이터 프로퍼티 enumerable와 같다
configurable데이터 프로퍼티 configurable와 같다.

접근자 함수는 getter/setter 함수라고도 부른다. 접근자 프로퍼티는 getter와 setter 함수를 모두 정의할 수도 있고 하나만 정의할 수도 있다.
※ getter 함수는 return 존재하도록 작성해야됨.

const person = {
  // 데이터 프로퍼티
  firstName: "Ungmo",
  lastName: "Lee",

  // getter 함수
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },

  // setter 함수
  set fullName(name) {
    [this.firstName, this.lastName] = name.split(" ");
  },
};

console.log(`${person.firstName} ${person.lastName}`); // Ungmo Lee
console.log(person.fullName); // Ungmo Lee

// fullName 값을 저장하면 setter가 호출된다.
person.fullName = "Heegun Lee";
console.log(person); // {firstName: 'Heegun', lastName: 'Lee'}

// fullName에 접근하면 getter가 호출된다.
console.log(person.fullName); // Heegun Lee

프로퍼티 디스크립터 비교

데이터 프로퍼티 반환시

let descriptorData = Object.getOwnPropertyDescriptor(person, "firstName");
console.log(descriptorData);
// {value: 'Ungmo', writable: true, enumerable: true, configurable: true}

접근자 프로퍼티 반환시

let descriptorAccessor = Object.getOwnPropertyDescriptor(person, "fullName");
console.log(descriptorAccessor);
// {get: ƒ, set: ƒ, enumerable: true, configurable: true}



프로퍼티 정의

https://www.youtube.com/watch?v=CPTq48Bl6Co

  • 프로퍼티 정의란 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것을 말한다.
  • 예를 들어 프로퍼티 값을 갱신 가능하도록 할 것인지, 프로퍼티를 재정의 가능하도록 할 것인지 정의할 수 있다.
  • 이를 통해 객체의 프로퍼티가 어떻게 동작해야 하는지 명확히 정의할 수 있다.

Object.defineProperty

Object.defineProperty 메소드를 사용하면 프로퍼티의 어트리뷰트를 정의할 수 있다. 인수는 객체의 참조와 프로퍼티의 키인 문자열 그리고 프로퍼티 디스크립터 객체를 전달한다.

데이터 프로퍼티 정의

const person = {};

Object.defineProperty(person, "firstName", {
  value: "Ungmo",
  writable: true,
  enumerable: true,
  configurable: true,
});

console.log(Object.getOwnPropertyDescriptor(person, "firstName"));
// {value: 'Ungmo', writable: true, enumerable: true, configurable: true}

디스크립터 객체의 프로퍼티 생략시, false가 기본값이다.

Object.defineProperty(person, "lastName", {
  value: "Lee",
});

console.log(Object.getOwnPropertyDescriptor(person, "lastName"));
// {value: 'Lee', writable: false, enumerable: false, configurable: false}

writable: false 이므로 [[value]] 값을 변경할 수 없다.

person.lastName = "kim";
console.log(person.lastName); // Lee

enumerable: false 이므로 for...in, Object.keys등 열거되지 않는다.

console.log(Object.keys(person)); // ['firstName']

configurable: false 이므로 프로퍼티 삭제시 무시된다.

delete person.lastName;
console.log(Boolean(person.lastName)); // true

접근자 프로퍼티 정의

Object.defineProperty(person, "fullName", {
  get() {
    return `${this.firstName} ${this.lastName}`;
  },

  set(name) {
    [this.firstName, this.lastName] = name.split(" ");
  },
  enumerable: true,
  configurable: true,
});

console.log(Object.getOwnPropertyDescriptor(person, "fullName"));
// {enumerable: true, configurable: true, get: ƒ, set: ƒ}

Object.definePropertys

Object.defineProperty 메소드는 한번에 하나의 프로퍼티만 정의할 수 있다. Object.defineProperties메소드를 사용하면 여러 개의 프로퍼티를 한번에 정의할 수 있다.

const person = {};

Object.defineProperties(person, {
  firstName: {
    value: "Ungmo",
    writable: true,
    enmerable: true,
    configurable: true,
  },
  lastName: {
    value: "Lee",
    writable: true,
    enmerable: true,
    configurable: true,
  },
  fullName: {
    get() {
      return `${this.firstName} ${this.lastName}`;
    },
    set(name) {
      [this.firstName, this.lastName] = name.split(" ");
    },
    enmerable: true,
    configurable: true,
  },
});

console.log(person.fullName); // Ungmo Lee

person.fullName = "Heegun Lee";
console.log(person.fullName); // Heegun Lee



객체 변경 방지

https://www.youtube.com/watch?v=llM1uf8kLMs

객체는 변경 가능한 값이므로 재활당없이 직접 변경이 가능하다. 즉, 프로퍼티를 추가하거나 삭제할 수 있고, 프로퍼티의 값을 갱신할 수 있으며 Object.defineProperty 또는 Object.definePropertys 메소드를 사용하여 프로퍼티 어트리뷰트를 재정의할 수도 있다.


자바스크립트는 객체의 변경을 방지할 수 있는 다양한 메소드를 제공한다. 객체 변경 방지 메소드 들은 객체의 변경을 금지하는 강도가 다르다.

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

객체 확장 금지

  • Object.preventExtensions 메소드는 객체의 확장을 금지한다.
  • 객체 확장 금지란, 프로퍼티 추가 금지를 의미한다.
  • 프로퍼티 동적 추가와 Object.defineProperty 사용한 방법 모두 금지된다.
  • 확장이 금지된 객체인지 여부는 Object.isExtensible 메소드로 확인가능함.

객체 확장 금지 전/후

const person = { name: "Lee" };
console.log(Object.isExtensible(person)); // true

// person 객체의 확장 금지(프로퍼티 추가 금지) 적용
Object.preventExtensions(person);
console.log(Object.isExtensible(person)); // false

프로퍼티 동적 추가시 무시됨

person.age = 20; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 추가는 금지되지만 삭제는 가능함

delete person.name;
console.log(person); // {}

객체 밀봉

  • Object.seal 메소드는 객체를 밀봉한다.
  • 객체 밀봉(seal)이란 프로퍼티 추가 및 삭제와 프로퍼티 어트리뷰트 재정의 금지를 의미함
  • 밀봉된 객체는 읽기와 쓰기(변경)만 가능하게된다.
  • 밀본된 객체 여부는 Object.isSealed 메소드로 확인 할 수 있다.

person 객체의 밀봉(seal) 전/후

const person = { name: "Lee" };
console.log(Object.isSealed(person)); // false

// 객체 밀봉으로 프로퍼티 추가, 삭제, 재정의가 금지된다.
Object.seal(person);
console.log(Object.isSealed(person)); // true

// 밀봉된 객체는 configurable 디스크립터가 false로 된다.
console.log(Object.getOwnPropertyDescriptors(person));
/*
{
  name: {value: 'Lee', writable: true, enumerable: true, configurable: false},
}
*/

프로퍼티 추가되지 않음

person.age = 20; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 삭제되지 않음

delete person.name; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 값 갱신은 가능

person.name = "kim";
console.log(person); // {name: 'kim'}

프로퍼티 어트리뷰트 재정의가 금지됨

Object.definedProperty(person, "name", { configurable: true });
// TypeError: Object.definedProperty is not a function

객체 동결

  • Object.freeze 메소드는 객체를 동결한다.
  • 프로퍼티 추가 및 삭제와 프로퍼티 어트리뷰트 재정의, 값 갱신 금지 한다.
  • 동결된 객체는 읽기만 가능하게 된다.
  • 동결된 객체인지 확인은 Object.isFrozen 메소드로 확인 할 수 있다.

person 객체의 동결(freeze) 전/후

const person = { name: "Lee" };
console.log(Object.isFrozen(person)); // false

// 객체 동결로 프로퍼티 추가, 삭제, 재정의, 쓰기를 금지한다.
Object.freeze(person);
console.log(Object.isFrozen(person)); // true

// 동결된 객체는 writable 디스크립터가 false로 된다.
console.log(Object.getOwnPropertyDescriptors(person));
/*
{
  name: {value: 'Lee', writable: false, enumerable: true, configurable: false},
}
*/

프로퍼티 추가되지 않음

person.age = 20; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 삭제되지 않음

delete person.name; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 값 갱신되지 않음

person.name = "Kim"; // 'use strict' 모드에서는 에러 발생됨
console.log(person); // {name: 'Lee'}

프로퍼티 어트리뷰트 재정의가 금지됨

Object.definedProperty(person, "name", { writable: true });
// TypeError: Object.definedProperty is not a function

불변 객체

profile
UI 마크업 개발자 장지훈입니다.

0개의 댓글