접근자 프로퍼티 (Accessor Property)

100pearlcent·2021년 9월 18일
0

JavaScript

목록 보기
13/22
post-thumbnail

접근자 프로퍼티

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

getter & setter

let obj = {
	get propName() {
    // getter
    // obj.propName로 프로퍼티 읽을 때 실행
    },
  
  	set propName(value) {
    // setter
    // obj.propName = value로 프로퍼티에 값을 할당하려 할 때 실행
    },
};
let user = {
	name: 'Jinju',
  	surname: 'Baek'
  
  	get fullName() {
    	return `${this.name} ${this.surname}`;
    },
  }
};

alert(user.fullName); // Jinju Baek

바깥 코드에서 접근자 프로퍼티를 일반 프로퍼티처럼 함수형식으로 호출하지 않고 일반 프로퍼티에서 값에 접근하는 것처럼 평범하게 user.fullName을 사용해 프로퍼티 값을 얻을 수 있다


let user = {
	name: 'Jinju',
  	surname: 'Baek'
  
  	get fullName() {
    	return `${this.name} ${this.surname}`;
    },
      
    set fullName(value) {
    	[this.name, this.surname] = value.split(' ');
    }

user.fullName = 'Jinju Baek';

alert(user.name); // Jinju
alert(user.surname); // Baek
};

위와 같이 getter, setter 메서드를 구현하면 객체엔 fullName이라는 가상의 프로퍼티가 생긴다
가상 프로퍼티는 읽고 쓸 순 있지만 실제로는 존재하지 않는다


접근자 프로퍼티 설명자

데이터 프로퍼티 설명자 != 접근자 프로퍼티 설명자

접근자 프로퍼티엔 설명자 valuewritable이 없는 대신에 getset이라는 함수가 있다

  • get: 인수가 없는 함수
  • set: 인수가 하나인 함수로, 프로퍼티에 값을 쓸 때 호출
  • enumerable: 데이터 프로퍼티와 동일
  • configurable: 데이터 프로퍼티와 동일
let user = {
	name: 'Jinju',
  	surname: 'Baek'
};

Object.defineProperty(user, 'fullName', {
  get() {
  	return `${this.name} ${this.surname}`;
  },
  set(value) {
  	[this.name, this.surname] = value.split(' ');
  }
});

alert(user.fullName); // Jinju Baek

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

위와 같이 defineProperty에 설명자 getset을 전달하면 fullName을 위한 접근자를 만들 수 있다


Object.defineProperty({}, 'prop', {
	get() {
    	return 1
    },
  
  	value: 2
}); 

⚠️ 프로퍼티는 접근자 프로퍼티(get/set를 가짐)나 데이터 프로퍼티(value를 가짐) 중 한 종류에만 속할 수 있다
= 한 프로퍼티에 getvalue를 동시에 설정하면 에러가 발생


getter & setter 활용

getter와 setter를 '실제'프로퍼티 값을 감싸는 wrapper처럼 사용하면, 프로퍼티 값을 원하는 대로 통제 가능하다

let user = {
	get name() {
    	return this._name;
    },
  
  	set name(value) {
    	if(value.length < 4) {
        alert('네 글자 이상 입력하세요');
        return;
        }
      	this._name = value;
    }
};

user.name = 'Jinju';
alert(user.name); // Jinju

name을 위한 setter를 만들어 user의 이름이 짧아지는 걸 방지한다.
실제 값은 별도 프로퍼티인 _name에 저장된다

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

user._name을 사용해서 이름에 바로 접근할 수 있으나 _로 시작하는 프로퍼티는 객체 내부에서만 활용하고, 외부에서는 건드리지 않는 것이 관습이다



호환성을 위해 사용

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

let john = new User('Jinju', 26);

alert(Jinju.age); // 26

위의 코드에서 요구사항이 바뀌어서 age 대신 birthday를 저장해야한다고 가정할 때, 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 jinju = new User('Jinju', new Date(1996, 10, 29));

alert(jinju.birthday);
alert(jinju.age);

0개의 댓글