일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 기업 협업
- 비절차적 데이터 조작어
- 뷰
- Oracle
- SQLD
- MYSQL
- 문법 차이
- execute immediate
- GROUPING
- coalesce
- window 함수
- show graph characteristics
- dense rank
- python
- list multiplication
- simple case expression
- searched case expression
- SQL
- html
- Node.js
- 코드 스니펫
- 정보처리기사
- 위코드
- git
- 정규식 연산
- sql 저장 모듈
- dom
- JavaScript
- 자료구조
- ROLLUP
- Today
- Total
프로그래밍 숲
func.call을 활용해 this undefind 해결하기 본문
오늘은 지난 시간에 이어서 코어 자바스크립트의 6.9 call/apply와 데코레이터, 포워딩에 대해서 공부해보도록 하겠습니다. 오늘은 'func.call'를 사용해 컨텍스트를 지정하는 것을 중점적으로 다뤄볼 예정입니다.
우선 사이트에서 주어진 예시코드는 아래와 같습니다.
// worker.slow에 캐싱 기능을 추가해봅시다.
let worker = {
someMethod() {
return 1;
},
slow(x) {
// CPU 집약적인 작업이라 가정
console.log(`slow(${x})을/를 호출함`);
return x * this.someMethod(); // (*)
},
};
// 이전과 동일한 코드
function cachingDecorator(func) {
let cache = new Map();
return function (x) {
if (cache.has(x)) {
return cache.get(x);
}
let result = func(x); // (**)
cache.set(x, result);
return result;
};
}
console.log(worker.slow(1)); // 기존 메서드는 잘 동작합니다.
worker.slow = cachingDecorator(worker.slow); // 캐싱 데코레이터 적용
console.log(worker.slow(2)); // 에러 발생!, Error: Cannot read property 'someMethod' of undefined
다른 것들은 지난 시간과 비슷한데, 마지막 콘솔로그 실행 시 에러가 발생한다는 점이 다릅니다. 이러한 에러가 발생하는 이유는 함수가 cachingDecorator로 래핑될 때 this의 값이 변경되기 때문입니다.
일반적으로 JavaScript에서 함수를 호출할 때 this는 호출 시점에 의해 결정됩니다. 원본 worker.slow 메서드를 호출할 때 this는 worker 객체를 참조합니다. 그러나 cachingDecorator 함수는 원본 함수의 동작을 변경하는 새로운 함수를 반환하며, 이 함수는 worker 객체의 메서드가 아니기 때문에 this가 undefined가 됩니다. 이를 this의 컨텍스트가 사라졌기 때문이라고 말합니다.
따라서 worker.slow(2)를 호출할 때 this.someMethod()에서 this는 undefined이므로 Cannot read property 'someMethod' of undefined와 같은 오류가 발생합니다.
해결 방법
this를 명시적으로 고정해주는 특별한 내장 함수 메서드 func.call(context, ...args) 사용합니다. 변경된 코드는 다음과 같습니다.
let worker = {
someMethod() {
return 1;
},
slow(x) {
console.log(`slow(${x})을/를 호출함`);
return x * this.someMethod(); // (*)
},
};
function cachingDecorator(func) {
let cache = new Map();
return function (x) {
if (cache.has(x)) {
return cache.get(x);
}
let result = func.call(this, x); // 이젠 'this'가 제대로 전달됩니다.
cache.set(x, result);
return result;
};
}
worker.slow = cachingDecorator(worker.slow); // 캐싱 데코레이터 적용
console.log(worker.slow(2)); // 제대로 동작합니다.
console.log(worker.slow(2)); // 제대로 동작합니다. 다만, 원본 함수가 호출되지 않고 캐시 된 값이 출력됩니다
이제 에러가 없이 발생하는 모습을 볼 수 있습니다.
'프로그래밍_인포 > Javascript' 카테고리의 다른 글
JavaScript | Array.prototype이 뭔가요? (0) | 2023.08.10 |
---|---|
Javascript | Number와 parseInt의 차이 (0) | 2023.08.10 |
자바스크립트에서 여러 개의 인자를 받는 데코레이터 함수 적용하기 (0) | 2023.06.25 |
자바스크립트 데코레이터와 캐싱: 함수 호출 결과 캐시 예제 분석 (0) | 2023.06.23 |
자바스크립트의 Window 객체: 전역 객체, 문서 객체 모델(DOM), 브라우저 객체 모델(BOM)이란? (0) | 2023.05.23 |