데코레이터를 이용하여 캐싱 기능 추가
데코레이터란 함수의 인수로 받은 함수의 행동을 변경시켜 주는것을 의미함
아래 코드는 데코레이터 함수를 이용하여 특정 함수에 캐싱 기능을 추가
function myFunc(num){
console.log(`${num}을 호출함`);
return num * num;
} // num을 호출받아서 num * num 의 결과를 리턴해주는 함수
function decoFunc(func){ // 함수의 cache를 생성해주는 데코레이터
let cache = new Map(); //캐시를 저장할 맵 생성
return function(num){
if(cache.has(num)){ //인수로 받은 num 키가 있을경우
return cache.get(num); //캐시에서 값을 불러옴
}else{
let res = func(num); // 키가 없을경우 num을 인수로 주어 myFunc 결과를 저장
cache.set(num,res);// num을 키, myFunc의 리턴값을 값으로 캐싱
return res;// 값을 반환
}
}
}
let deco = decoFunc(myFunc);
console.log(deco(1));
console.log(deco(1));
console.log(deco(2));
console.log(deco(2));
해당 인수로 전해준 값을 처음 호출할때는 캐싱이 되어있지 않아서 myFunc함수 자체가 실행이 되지만 두번째 부터는 캐시에 저장이 되기 때문에 데코레이터 내부의 캐시에서 캐싱되어있는 값만 가져올 수 있음
이러한 데코레이터를 사용하면 데코레이터를 재사용 할 수 있고, 캐싱로직을 함수의 로직과 분리하여 복잡성이 줄어든다는 이점이 있음
func.call 사용
만약 데코레이터의 인자로 this가 사용되는 객체 메서드를 사용하면 정상적으로 작동되지 않음.
decoFunc는 위에 코드를 그대로 사용한다고 가정
let obj = {
someNum(){ return 2; },
myFunc(num){ return this.someNum() * num; }
}
let deco = decoFunc(obj.myFunc);
console.log(deco(2));
decoFunc에 인자로 전해줄 때 myFunc의 this 는 obj가 아니라 undefined이기 때문에 에러가 발생함
이러한 문제를 해결하기 위해 func.call 을 사용하여 컨텍스트를 지정해줄 수 있음
func.call의 문법은 아래와 같음
func.call(context[,arg1, arg2 ...])
- context : this로 사용할 컨텍스트
- arg: 함수의 인자로 전달할 값들(생락가능)
func.call 을 사용하여 위의 코드를 수정
let obj = {
someNum(){ return 2; },
myFunc(num){ return this.someNum() * num; }
}
function decoFunc(func){
let cache = new Map();
return function(num){
if(cache.has(num)){
return cache.get(num);
}else{
let res = func.call(obj,num); // obj를 this로 설정
cache.set(num,res);
return res;
}
}
}
let deco = decoFunc(obj.myFunc);
console.log(deco(2));
컨텍스트로 obj를 추가하여 this가 obj로 설정되므로 값이 제대로 들어간 것을 볼 수 있음
func.apply
func.apply 는 func.call 과 같은 기능을 하지만, 함수의 인자를 전달할 때 배열을 이용하여 전달함
func.apply(context,args)
같은 함수를 apply와 call을 이용하여 인자를 전달
function addNums(a,b,c){ return a+b+c; }
let call = addNums.call(null,1,2,3) // call 은 인자를 전달하기 위해 1,2,3을 인수로 전달
let apply = addNums.apply(null,[1,2,3]) // apply는 인자의 개수에 맞춰서 하나의 배열로 전달
console.log(call)
console.log(apply)
두 변수의 결과가 동일한 것을 확인할 수 있음
참조: https://ko.javascript.info/call-apply-decorators
'JavaScript > JavaScript기초' 카테고리의 다른 글
[Javascript] 프로퍼티 플래그와 설명자 (0) | 2021.09.27 |
---|---|
[Javascript] 함수 바인딩 (0) | 2021.09.27 |
[Javascript] setTimeout과 setInterval (0) | 2021.09.24 |
[Javascript] 재귀와 스택 (0) | 2021.09.16 |
[Javascript] 전역객체 (0) | 2021.09.10 |