JavaScript - 접근자 프로퍼티 (getter, setter)

BigbrotherShin·2020년 1월 29일
19

JavaScript

목록 보기
7/17
post-thumbnail

1. 프로퍼티의 종류

  • 데이터 프로퍼티(data property) : 값을 저장하기 위한 프로퍼티. 일반적으로 사용하는 프로퍼티는 데이터 프로퍼티입니다. 데이터 프로퍼티 조작 방법에 대해선 모두 알고 계실 것이라 생각합니다.

  • 접근자 프로퍼티(accessor property) : 값이 없음. 프로퍼티를 읽거나 쓸 때 호출하는 함수를 값 대신에 지정할 수 있는 프로퍼티입니다. 접근자 프로퍼티의 본질은 함수인데, 이 함수는 값을 획득(get)하고 설정(set)하는 역할을 담당합니다. 그런데 외부 코드에서는 함수가 아닌 일반적인 프로퍼티처럼 보입니다.

2. 접근자 프로퍼티

접근자란 객체 지향 프로그래밍에서 객체가 가진 프로퍼티 값을 객체 바깥에서 읽거나 쓸 수 있도록 제공하는 메서드를 말합니다. 객체의 프로퍼티를 객체 바깥에서 직접 조작하는 행위는 데이터의 유지 보수성을 해치는 주요한 원인입니다. - 아소 히로시, 모던 자바스크립트 입문 9.3

2.1. getter와 setter

접근자 프로퍼티는 'getter(획득자)'와 ‘setter(설정자)’ 메서드로 표현됩니다. 객체 리터럴 안에서 getter와 setter 메서드는 get과 set으로 나타낼 수 있습니다.

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

 set propName(value) {
   // setter, obj.propNAme = value를 실행할 때 실행되는 코드
 }
};
  • getter 메서드는 obj.propName을 사용해 프로퍼티를 읽으려고 할 때 실행됩니다.
  • setter 메서드는 obj.propNAme = value으로 프로퍼티에 값을 할당하려 할 때 실행됩니다.

2.1.1 getter 메서드

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

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

alert(user.fullName); // John Smith

바깥 코드에선 접근자 프로퍼티를 일반 프로퍼티처럼 사용할 수 있습니다. 접근자 프로퍼티는 이런 아이디어에서 출발했습니다. 접근자 프로퍼티를 사용하면 함수처럼 호출 하지 않고, 일반 프로퍼티에서 값에 접근하는 것처럼 평범하게 user.fullName을 사용해 프로퍼티 값을 얻을 수 있습니다. 나머지 작업은 getter 메서드가 뒷단에서 처리해줍니다.

한편, 위 예시의 fullName은 getter 메서드만 가지고 있기 때문에 user.fullName=을 사용해 값을 할당하려고 하면 에러가 발생합니다.

let user = {
  get fullName() {
    return `...`;
  }
};

user.fullName = "Test"; // Error (프로퍼티에 getter 메서드만 있어서 에러가 발생합니다.)

2.1.2 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 Special"

alert(user.fullName); // Alice Special
alert(user.name); // Alice
alert(user.surname); // Special

이렇게 getter와 setter 메서드를 구현하면 객체엔 fullName이라는 '가상’의 프로퍼티가 생깁니다. 가상의 프로퍼티는 읽고 쓸 순 있지만 실제로는 존재하지 않습니다.

2.2. 접근자 프로퍼티 설명자

데이터 프로퍼티의 설명자와 접근자 프로퍼티의 설명자는 다릅니다.

접근자 프로퍼티엔 설명자 value와 writable가 없는 대신에 get과 set이라는 함수가 있습니다.

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

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

아래와 같이 defineProperty에 설명자 get과 set을 전달하면 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를 가짐) 중 한 종류에만 속하고 둘 다에 속할 수 없다는 점을 항상 유의하시기 바랍니다.

주석: Object.defineProperty

출처: Object.defineProperty() - JavaScript | MDN

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false
});

object1.property1 = 77;
// throws an error in strict mode

console.log(object1.property1);
// expected output: 42

구문

Object.defineProperty(obj, prop, descriptor)

매개변수

obj
속성을 정의할 객체.
prop
새로 정의하거나 수정하려는 속성의 이름 또는 Symbol.
descriptor
새로 정의하거나 수정하려는 속성을 기술하는 객체.

반환 값

주어진 대상 obj.

3. getter와 setter 똑똑하게 활용하기

일반적으로 이름을 읽고 수정하는 객체는 다음과 같이 이름을 수정하는 메서드 setName()을 포함하고 있습니다.

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

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

user.setName(""); // 너무 짧은 이름을 할당하려 함

그러나 getter와 setter를 ‘실제’ 프로퍼티 값을 감싸는 래퍼(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 = ""; // 너무 짧은 이름을 할당하려 함

user의 이름은 _name에 저장되고, 프로퍼티에 접근하는 것은 getter(user.name)와 setter(user.name = value)를 통해 이뤄집니다.

기술적으론 외부 코드에서 user._name을 사용해 이름에 바로 접근할 수 있습니다. 그러나 밑줄 (user._name) 로 시작하는 프로퍼티는 객체 내부에서만 활용하고, 외부에서는 건드리지 않는 것이 관습입니다. 위의 예제에서 user.name을 통해 프로퍼티에 접근하고 수정하는 것 처럼 user._name을 직접적으로 사용하지는 않는 것이 좋습니다.

출처 : 프로퍼티 getter와 setter | JAVASCRIPT.INFO

profile
JavaScript, Node.js 그리고 React를 배우는

2개의 댓글

comment-user-thumbnail
2020년 7월 21일

감사합니다 ㅎㅎ

답글 달기
comment-user-thumbnail
2021년 1월 2일
let user = {
  get fullName() {
    return `...`;
  }
};

user.fullName = "Test";

이걸 콘솔에 찍어보면 오류가 안나는데 어떻게하면 오류를 볼수있나요?

답글 달기