TIL 84 | getter와 setter

meow·2020년 12월 2일
0

JavaScript

목록 보기
32/46

코어자바스크립트 : 프로퍼티 getter와 setter

객체의 프로퍼티는 데이터 프로퍼티접근자 프로퍼티로 나뉜다.

  • 데이터 프로퍼티(data property)
    지금까지 사용한 모든 프로퍼티
  • 접근자 프로퍼티(accesor property)
    새로운 종류의 프로퍼티. 접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)하고 설정(set)하는 역할을 담당한다. 그런데 외부 코드에서는 함수가 아닌 일반적인 프로퍼티처럼 보인다.

getter와 setter

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

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

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

즉 getter 메서드는 프로퍼티를 읽으려고 할 때 실행되고, setter 메서드는 프로퍼티에 값을 할당하려 할 때 실행된다.

getter

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

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

alert(user.fullName); // John Smith

기존 값을 복사-붙여넣기 하지 않고도 getter 메서드로 구현한 코드이다. 바깥 코드에서는 접근자 프로퍼티를 일반 프로퍼티처럼 사용할 수 있다. 마치 일반 프로퍼티 값에 접근하는 것 처럼 user.fullName을 사용해서 값을 얻을 수 있다. 하지만 위 코드는 getter 메서드만 가지고 있기 때문에 user.fullName= 형식으로 값을 할당하려하면 에러가 난다.

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

setter 메서드를 추가해서 값을 할당할 수 있도록 만들었다.

접근자 프로퍼티 설명자

접근자 프로퍼티는 데이터 프로퍼티와는 다른 설명자를 가지고 있다. 접근자 프로퍼티에는 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) 중 한 종류에만 속할 수 있다. 둘 다 속하는 것 불가능하다!

// Error: Invalid property descriptor.
Object.defineProperty({}, 'prop', {
  get() {
    return 1
  },

  value: 2
});

wrapper로 사용하기

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 = ""; // 너무 짧은 이름을 할당하려 함

접근자 프로퍼티를 실제 프로퍼티 값을 감싸는 래퍼로 사용하면 위와 같이 프로퍼티 값을 원하는 대로 통제할 수 있다.

호환성을 위해 사용하기

접근자 프로퍼티는 getter와 setter를 사용해서 데이터 프로퍼티의 행동과 값을 원하는 대로 조정할 수 있게 해준다는 점에서 유용하다.

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

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

alert( john.age ); // 25

위 코드에서 age 대신에 birthday를 저장해야 한다면?

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

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

이렇게 하면 기존 코드 중 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 역시 사용할 수 있습니다.

우..와 대박이다......

profile
🌙`、、`ヽ`ヽ`、、ヽヽ、`、ヽ`ヽ`ヽヽ` ヽ`、`ヽ`、ヽ``、ヽ`ヽ`、ヽヽ`ヽ、ヽ `ヽ、ヽヽ`ヽ`、``ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ`ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ、ヽ、ヽ``、ヽ`、ヽヽ 🚶‍♀ ヽ``ヽ``、ヽ`、

0개의 댓글