안녕하세요 이번 포스팅의 내용입니다.
class에서 get과 set사용하기
지난 게시물의 소스코드를 사용합니다. (Ctrl + Click)
1. class에서 get과 set사용하기
class Coupon {
constructor (price, expiration) {
this.price = price;
this.expiration = expiration || '2주'
}
get getPriceText () {
return `$${this.price}`
}
get getExpirationMessage () {
return `이 쿠폰은 ${this.expiration}후에 만료됩니다.`
}
set halfPrice(price) {
this.price = price / 2
}
}
const coupon = new Coupon(5)
coupon.halfPrice = 20;
console.log(coupon.price)
console.log(coupon.getPriceText) // $5
get함수로 getPriceText() 와 getExpirationMessage() 를 설정했고,
set함수로 halfPrice() 를 설정했습니다.
set함수에는 변수처럼 값을 할당할 수 있습니다.
get의 경우 coupon.getPriceText로 접근해 뒤에 괄호를 붙이지않아 속성처럼 보이게 할 수 있습니다.(마지막 줄)
class Coupon {
constructor (price, expiration) {
this.price = price;
this.expiration = expiration || '2주'
}
get price() {
return this.price;
}
set price(price) {
this.price = `$ ${price}`
}
}
const coupon = new Coupon(5)
// result
RangeError: Maximum call stack size exceeded
인스턴스 생성과 동시에 에러가 발생합니다.
이럴 경우 코딩컨벤션에 따라 속성명 앞에 밑줄 _ 을 입력해 속성이 비공개라는 점을 표시합니다.
class Coupon {
constructor (price, expiration) {
this._price = price;
this.expiration = expiration || '2주'
}
get price() {
return this._price;
}
set price(price) {
const newPrice = price.toString().replace(/[^\d]/g,'')
this._price = parseInt(newPrice, 10);
}
}
const coupon = new Coupon(5)
coupon.price = '15a'
console.log(coupon.price) // 15
set price()함수는 다음의 과정을 거칩니다.
2. class에 generator 함수를 이용해 이터러블속성 생성하기
이터러블 속성을 생성하면 컬렉션을 순회할 수 있게됩니다.
class FamilyTree {
constructor () {
this.family = {
name : 'Doris',
child : {
name : 'Martha',
child : {
name : 'Dyan',
child : {
name : 'Bea'
}
}
}
}
}
getMembers () {
const family = []
let node = this.family
while(node){
family.push(node.name)
node = node.child
}
return family
}
}
const family = new FamilyTree()
console.log(family.getMembers())
// result
[ 'Doris', 'Martha', 'Dyan', 'Bea' ]
FamilyTree클래스는 중첩구조의 속성 family를 가지고있습니다. 가계도입니다.
제너레이터를 사용하면 getMember 함수가 필요없어집니다.
class FamilyTree {
...
생성자 생략
...
* [Symbol.iterator]() {
let node = this.family
while (node) {
yield node.name
node = node.child
}
}
getMember함수를 없애고 iterator를 넣었습니다.
이제 이 클래스는 iterable입니다.
generator함수를 이용하면 이터레이터를 쉽게 구현할 수 있습니다.
펼침연산자를 이용해 순회해보겠습니다.
const family = new FamilyTree()
console.log([...family])
// result
[ 'Doris', 'Martha', 'Dyan', 'Bea' ]
잠시 짧게 iterator, iterable에 대해서 간단히 보겠습니다.
정리하면 iterator속성을 제대로 구현했다면 해당 객체는 iterable입니다.
generator은 iterator을 만드는 방법중 가장 쉬운 방법입니다.
generator을 사용하지 않고도 iterator을 [Symbol.iterator]
key를 만들어서 구현할 수 있지만 조금 더 복잡합니다.
3. class에서의 bind()와 화살표함수
이름을 인수로 받아 인사메세지를 반환하는 함수입니다.
class Greeting {
constructor () {
this.message = '님 안녕하세요?'
}
setMessage(name) {
return `${name}${this.message}`
}
setMessages (...names) {
return names.map(this.setMessage)
}
}
const greeting = new Greeting()
const names = ['a','b','c']
console.log(greeting.setMessage('a'))
// a님 안녕하세요?
console.log(greeting.setMessages(...names))
// TypeError: Cannot read property 'message' of undefined
배열메서드를 사용하는 경우 에러를 반환합니다.
지난 포스팅에서 객체리터럴과 마찬가지로 배열메서드 map()이 새로운 문맥을 만들어 this바인딩을 생성하기 때문에 에러가 발생합니다.
class Greeting {
constructor () {
this.message = '님 안녕하세요?'
}
setMessage = (name) => `${name} ${this.message}`
setMessages (...names) {
return names.map(this.setMessage)
}
}
const greeting = new Greeting()
const names = ['a','b','c']
console.log(greeting.setMessages(...names))
// result
[ 'a 님 안녕하세요?', 'b 님 안녕하세요?', 'c 님 안녕하세요?' ]
2-1 메서드에서 연결
class Greeting {
constructor () {
this.message = '님 안녕하세요?'
}
setMessage (name) {
return `${name}${this.message}`
}
setMessages (...names) {
return names.map(this.setMessage.bind(this))
}
}
메서드에서 연결할 때의 단점은 다른메서드에서 setMessage를 사용하려면 다시 bind()로 묶여줘야 한다는 겁니다.
2-2 생성자에서 연결
class Greeting {
constructor () {
this.message = '님 안녕하세요?'
this.setMessage = this.setMessage.bind(this)
}
setMessage (name) {
return `${name}${this.message}`
}
setMessages (...names) {
return names.map(this.setMessage)
}
}
생성자에서 연결할 때의 단점은 생성자가 비대해집니다