Skip to content

Latest commit

 

History

History
169 lines (121 loc) · 4.37 KB

4주차.md

File metadata and controls

169 lines (121 loc) · 4.37 KB

프로퍼티 플래그와 설명자

프로퍼티를 단순히 키-값 쌍의 관점말고도 다르게 사용할 수 있다.

프로퍼티 플래그

객체 프로퍼티는 값(value) 과 함께 플래그(flag)라 불리는 특별한 속성 세 가지를 갖는다.

  • writable - true이면 값을 수정할 수 있다.
  • enumerable - true이면 반복문을 사용해 나열할 수 있다.
  • configurable - true이면 프로퍼티 삭제나 플래그 수정이 가능하다.

지금까지 해왔던 ‘평범한 방식’으로 프로퍼티를 만들면 해당 프로퍼티의 플래그는 모두 true가 된다.

Object.getOwnPropertyDescriptor 메서드를 사용하면 특정 프로퍼티에 대한 정보를 모두 얻을 수 있다.

let user = {
  name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/* property descriptor:
{
  "value": "John",
  "writable": true,
  "enumerable": true,
  "configurable": true
}
*/

Object.defineProperty를 사용하면 플래그를 변경할 수 있다.

writable / enumerable / configurable

  • writable: 값을 쓰지 못하도록 할 수 있다.
let user = {
  name: "John"
};

Object.defineProperty(user, "name", {
  writable: false
});

user.name = "Pete"; // Error: Cannot assign to read only property 'name'
  • enumerable: for…in 반복문에 나타나지 않게 할 수 있다.
let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

Object.defineProperty(user, "toString", {
  enumerable: false
});

// 이제 for...in을 사용해 toString을 열거할 수 없게 되었습니다.
for (let key in user) alert(key); // name
  • configurable: 구성 가능하지 않음을 나타내는 플래그로 객체를 지울 수 없게 할 수 있다.
let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');

Math.PI = 3.14; // ERROR

프로퍼티 getter와 setter

접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)하고 설정(set)하는 역할을 담당한다. 외부 코드에서는 함수가 아닌 일반적인 프로퍼티처럼 보인다.

getter와 setter

접근자 프로퍼티는 getter와 setter 메서드로 표현된다. 객체 리터럴 안에서 getter와 setter 메서드는 getset 으로 나타낼 수 있다.

let obj = {
  get propName() {
    // getter, obj.propName을 실행할 때 실행되는 코드
  },

  set propName(value) {
    // setter, obj.propName = value를 실행할 때 실행되는 코드
  }
};

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
};

alert(user.fullName); // John Smith

위의 예시에서는 getter 메서드만 가지고 있기 때문에 수정하는 것은 불가능하다.

수정을 하기 위해서는 setter 메서드를 설정해야 한다.

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    [this.name, this.surname] = value.split(" ");
  }
};

// 주어진 값을 사용해 set fullName이 실행됩니다.
user.fullName = "Alice Cooper";

alert(user.name); // Alice
alert(user.surname); // Cooper

접근자 프로퍼티 설명자

  • get: 인수가 없는 함수로, 프로퍼티를 읽을 때 동작함
  • set: 인수가 하나인 함수로, 프로퍼티에 값을 쓸 때 호출됨
  • enumerable: 데이터 프로퍼티와 동일함
  • configurable: 데이터 프로퍼티와 동일함

getter, setter 똑똑하게 활용하기

실제 프로퍼티 값을 감싸는 래퍼처럼 사용하면, 프로퍼티 값을 원하는 대로 통제할 수 있다.

아래 예시에선 name 을 위한 setter를 만들어 user 의 이름이 너무 짧아지는 걸 방지하고 있다. 실제 값은 별도의 프로퍼티 _name 에 저장된다.

let user = {
  get name() {
    return this._name;
  },

  set name(value) {
    if (value.length < 4) {
      alert("입력하신 값이 너무 짧습니다. 네 글자 이상으로 구성된 이름을 입력하세요.");
      return;
    }
    this._name = value;
  }
};

user.name = "Pete";
alert(user.name); // Pete

user.name = ""; // 너무 짧은 이름을 할당하려 함

user의 이름은 _name에 저장되고, 프로퍼티에 접근하는 것은 getter와 setter를 통해 이뤄진다.