Javascript 접근자 프로퍼티 (Getters and Setters)

Garam·2023년 10월 30일
0

The Odin Project

목록 보기
11/14
post-thumbnail

Summary of: https://javascript.info/property-accessors


Properties

객체의 프로퍼티는 두 종류로 나뉜다.

  1. 데이터 프로퍼티 (Data property): 지금까지 사용한 모든 프로퍼티.
  2. 접근자 프로퍼티 (Accessor property): 본질은 함수. 값을 획득(get)하고 설정(set)하는 역할을 담당. 외부 코드에서는 일반적인 프로퍼티처럼 쓰임.


Getters and Setters

접근자 프로퍼티는 gettersetter 메소드로 표현된다.

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
  • 만약 setter 메소드 없이 getter 메소드만 있다면 user.fullName=을 사용해 값 할당 시 에러 발생
  • fullName은 가상의 프로퍼티다. 읽고 쓸 수 있지만 실제로 존재하지 않음


Accessor descriptors

접근자 프로퍼티의 설명자(descriptors)에는 valuewritable가 없는 대신에 getset이라는 함수가 있다.

따라서 접근자 프로퍼티는 다음과 같은 설명자를 갖는다.

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

아래와 같이 defineProperty에 설명자 getset을 전달하면 fullName 접근자 생성이 가능하다.

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

Object.defineProperty(user, 'fullName', {
  get() {
    return `${this.name} ${this.surname}`;
  },

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

alert(user.fullName); // John Smith

for(let key in user) alert(key); // name, surname

프로퍼티는 데이터 프로퍼티나 접근자 프로퍼티 중 한 종류에만 속할 수 있다.
교집합은 존재하지 않는다. 따라서 get/set 메서드와 value를 둘 다 설정하면 에러가 발생한다.



실제 값 은닉하기

실제 값은 _name이라는 private 변수에 별도로 저장하면서 setter를 이용해 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을 통해 외부에서 접근할 수 있긴 하지만 가능하면 건드리지 않는 것이 관습이다.



Compatibility

function User(name, age) {
  this.name = name;
  this.age = age;
}

let john = new User("John", 25);

alert( john.age ); // 25

위의 코드에서 만약 age 대신 더욱 정확하고 편리한birtyday를 써야 한다는 요구를 받는다면?

만약 생성자 함수를 직접 수정하면 기존에 age를 사용하는 모든 코드를 찾아서 일일이 수정해야 하는 번거로움이 있다.

여기서 age를 위한 getter를 추가한다면 (=접근자를 생성한다면) 문제를 쉽게를 해결할 수 있다.

function User(name, birthday) {
  this.name = name;
  this.birthday = birthday;

  // age는 현재 날짜와 생일을 기준으로 계산됩니다.
  Object.defineProperty(this, "age", {
    get() {
      let todayYear = new Date().getFullYear();
      return todayYear - this.birthday.getFullYear();
    }
  });
}

let john = new User("John", new Date(1992, 6, 1));

alert( john.birthday ); // birthday를 사용할 수 있습니다.
alert( john.age );      // age 역시 그대로 사용할 수 있습니다.


0개의 댓글