자바스크립트의 프로퍼티는 성질에 따라서 데이터 프로퍼티와 접근자 프로퍼티로 구분합니다. 이번 시간에는 접근자 프로퍼티와 관련된 얘기입니다.
이해를 돕기 위해서 예를 들어 보면, 자바언어에서 getter, setter 메소드는 로직을 위한 메소드가 아니라 객체가 갖고 있는 변수에 접근해서 값을 가져가거나 수정하는 용도로 사용하는 메소드입니다. 부가적으로 값을 가공하는 로직정도를 두기도 합니다.
자바스크립트는 자바언어에서 지원하는 접근자(예: private, protected, public) 개념이 없기 때문에 자바스크립트의 게터, 세터를 단지 프로퍼티의 값을 접근하거나 수정하는 용도로 사용한다면 사실 큰 의미가 없습니다. 프로퍼티에 직접 접근해서 사용할 수 있기 때문이지요. 차라리, 자바스크립트의 게터, 세터는 값을 조작해서 가져가거나 조작해서 수정하고자 하는 부가적인 로직을 두고 싶은 경우에 사용한다고 이해하시는게 좋겠습니다.
(AngularJS,React를 위한 자바스크립트)getter, setter of class_AngularJS교육/ReactJS교육/자바스크립트교육추천
1. { for AngularJS, React}
고급 자바스크립트
4. getter, setter ofclass
탑크리에듀
IT기술 칼럼
와 함께하는
2. { ES6 }4. getter, setter of class
자바스크립트의 프로퍼티는 성질에 따라서 데이터 프로퍼티와 접근자 프로퍼티로
구분합니다. 이번 시간에는 접근자 프로퍼티와 관련된 얘기입니다.
이해를 돕기 위해서 예를 들어 보면, 자바언어에서 getter, setter 메소드는 로직을
위한 메소드가 아니라 객체가 갖고 있는 변수에 접근해서 값을 가져가거나 수정하
는 용도로 사용하는 메소드입니다.
부가적으로 값을 가공하는 로직정도를 두기도 합니다.
자바스크립트는 자바언어에서 지원하는 접근자(예: private, protected, public) 개념
이 없기 때문에 자바스크립트의 게터, 세터를 단지 프로퍼티의 값을 접근하거나 수
정하는 용도로 사용한다면 사실 큰 의미가 없습니다.
프로퍼티에 직접 접근해서 사용할 수 있기 때문이지요. 차라리, 자바스크립트의 게
터, 세터는 값을 조작해서 가져가거나 조작해서 수정하고자 하는 부가적인 로직을
두고 싶은 경우에 사용한다고 이해하시는게 좋겠습니다.
3. { ES6 }4. getter, setter of class
class4.es6
classCar{
constructor(name){
this.name= name;
}
get_name(){
returnthis.name;
}
set_name(name){
this.name= name;
}
}
varcar= newCar('A');
console.log(car);
//{ name:'A'}
자바스크립트는 클래스문법에서 get, set 키워드로 정의하는 함수 선언방법을 도입했습니다.
우선, 클래스 문법의 사용예제를 살펴보겠습니다.
4. { ES6 }4. getter, setter of class
console.log(Object.getOwnPropertyNames(Car.prototype));
//['constructor','_name']
console.log(Object.getOwnPropertyDescriptor(Car.prototype,'_name'));
/*
{ get:[Function:get_name],
set:[Function:set_name],
enumerable:false,
configurable:true}
*/
console.log(car._name);//getter
//A
car._name= 'B';// 할당연산자와같이사용하면setter
console.log(car._name);
//B
선언방법은 함수 앞에 get, set 키워드를 설정하는 것 입니다.
get, set키워드가 붙은 함수명은 일반적으로 같은 이름을 사용합니다. 이렇게 선언된 게터, 세
터 메소드를 통해 객체가 갖고 있는 변수에 접근하는 것을 제어합니다. 다른 랭귀지에서의 게
터, 세터 메소드와 사용 용도는 같지만 이용하는 방법은 차이가 있습니다.
5. { ES6 }4. getter, setter of class
console.log(car._name);//getter
//A
car._name= 'B';// 할당연산자와같이사용하면setter
console.log(car._name);
//B
자바스크립트의 게터, 세터 메소드는 괄호없이 사용해야 합니다. 할당연산자가 없으면 게터로
작동하고 할당연산자와 같이 사용하면 세터로 작동합니다.
console.log(Object.getOwnPropertyNames(Car.prototype));
//[ 'constructor','_name']
자바스크립트의 게터, 세터 메소드는 생성자 함수의 프로토타입 객체에 추가되며 get, set 두
개의 함수는 결국 하나의 프로퍼티의 서술자 객체의 속성으로 반영되어 처리됩니다.
6. { ES6 }4. getter, setter of class
console.log(Object.getOwnPropertyDescriptor(Car.prototype,'_name'));
/*
{ get:[Function:get_name],
set:[Function:set_name],
enumerable:false,
configurable:true}
*/
자바스크립트의 get, set 설정으로 추가된 프로퍼티는 접근자 프로퍼티입니다.
get: 값을조회하는함수다.기본값은undefined이다.
set:값을수정하는함수다.기본값은undefined이다.
enumerable:for-in루프나Object.keys()메소드를사용하여열거할수있다.
configurable:프로퍼티속성을변경,삭제할수있다.
접근자 프로퍼티의 속성을 정의하는 서술자 객체의 프로퍼티의 용도는 다음과 같습니다.
7. { ES6 }4. getter, setter of class
이해를 돕기 위해서, 똑같은 결과를 얻을 수 있는 코드를 ES5 함수문법으로 작성해서 살펴보
겠습니다.
functionCar(name){
this.name=name;
}
Object.defineProperty(Car.prototype,'_name',{
get:function(){
returnthis.name;
},
set:function(name){
this.name= name;
},
enumerable:false,
configurable:true
});
varcar= newCar('A');
console.log(car);
//{ name:'A' }
console.log(Object.getOwnPropertyNames(Car.prototype));
//[ 'constructor','_name']
example4.js
8. { ES6 }4. getter, setter of class
console.log(Object.getOwnPropertyDescriptor(Car.prototype,'_name'));
/*
{ get:[Function:get_name],
set:[Function:set_name],
enumerable:false,
configurable:true}
*/
console.log(car._name);//getter
//A
car._name= 'B';//할당연산자와같이사용하면setter
console.log(car._name);
//B
그런데, 객체의 변수 name에 직접 접근할 수 있는 데, 접근자 프로퍼티를 설정하여
get, set 함수를 둘 필요가 있을까요?
get, set 함수에 부가적인 처리로직을 둔다면 의미가 생깁니다.
반대로 값을 가져가거나 수정할 때 처리하는 부가적인 로직이 없다면 접근자 프로퍼티를 둘
필요가 없습니다.
9. { ES6 }4. getter, setter of class
example4-2.js
functionCar(name){
//this.name= name;// 아래코드로대체한다.
Object.defineProperty(this,'name',{
value:name,
writable:false,
enumerable:true,
configurable:true
});
}
프로퍼티 서술자 객체를 사용하여 새로 만들어지는 객체에 프로퍼티 ‘name’을 추가합니다.
이 때, 프로퍼티 속성 중 writable 값을 false로 선언합니다.
이러면 이 프로퍼티의 값은 변경할 수 없게 됩니다. 그래서, 다음과 같은 현상이 벌어집니다.
“car._name=’B’” 처럼 세터를 사용하여도 “car.name=’B’” 처럼 직접 프로퍼티를 수정하려고
시도하여도 변경되지 않으며 예외도 발생하지 않습니다.
값이 변경되지 않는데 예외가 발생하지 않는군요!
10. { ES6 }4. getter, setter of class
console.log(car._name);
//A
car._name= 'B';
console.log(car._name);
//A
세터를 사용하는 경우 다음처럼 예외를 던져 친절하게 수정할 수 없다고 알려 줄 수 있습니다.
Object.defineProperty(Car.prototype,'_name',{
get:function(){
returnthis.name;
},
//set:function(name){ //아래코드로대체한다.
// this.name=name;
//},
set:function(name){
thrownewError('값을변경할수없습니다.');
},
enumerable:false,
configurable:true
});
11. { ES6 }4. getter, setter of class
그러나, 사용자가 세터를 통해서 값에 접근하지 않고 직접 값을 갖고 있는 프로퍼티에 접근할
수 있기 때문에 완전한 해결책은 아닙니다. 따라서, 데이터 프로퍼티 접근 시 무언가 로직을
수행하여 사용자에게 알려줄 수 있는 방법이 필요하다는 결론에 다다르게 됩니다.
이 때, 프록시 객체의 필요성이 대두됩니다. 아래 example4-3.js에서 사용방법을 살펴보겠습니
다.
다음은 테스트를 위해 변경한 전체 소스코드입니다.
example4-2.js
functionCar(name){
//this.name= name;
Object.defineProperty(this,'name',{
value:name,
writable:false,
enumerable:true,
configurable:true
});
}
16. { ES6 }4. getter, setter of class
원래 값을 갖고 있는 car 객체가 target입니다. 이를 프록시 객체로 감싼 객체를 변수 proxyCar
가 가리킵니다.
타겟 객체에 접근하기 전 프록시객체 생성 시 설정한 handler 객체의 트랩함수가 기동합니다.
이 때, “writable: false”로 설정된 name 프로퍼티를 수정하고 하는 경우 예외를 발생시켜 사용
자에게 알려주는 방식입니다.
이번 시간의 주제로 돌아옵니다. 자바스크립트의 객체 프로퍼티는 두 가지 용도로 사용될 수
있다는 것을 기억하시면 좋겠습니다.
1. 데이터 프로퍼티 : 변수, 함수를 보관한다.
2. 접근자 프로퍼티 : 변수, 함수의 접근 시 부가적인 작업을 수행한 후 데이터 프로퍼티와 연계한다.
객체 프로퍼티의 두 가지 용도
17. { ES6 }4. getter, setter of class
게터, 세터의 필요성 및 서술자 속성의 역할이 무엇인지 파악할 수 있는 예제를 살펴보면서 마
치도록 하겠습니다.
example-configurable.js
varperson={};
Object.defineProperty(person,'name',{
value:'B',
writable:true,
enumerable:true,
configurable:false
});
console.log(Object.getOwnPropertyDescriptor(person,'name'));
//{ value:'B',
// writable:true,
// enumerable:true,
// configurable:true}
18. { ES6 }4. getter, setter of class
console.log(person);
//{ name:'B'}
person.name= 'A';
console.log(person);
//{ name:'A'}
deleteperson.name;//configurable:false설정으로삭제되지않는다.
console.log(Object.getOwnPropertyDescriptor(person,'name'));
//{ value:'A',
// writable:true,
// enumerable:true,
// configurable:false}
“delete person.name;” 코드는 name 프로퍼티의 서술자 설정 중, “configurable: false” 설정으
로 삭제되지 않습니다.