call/apply와 데코레이터, 포워딩

파랑·2021년 8월 19일
0

함수를 어떻게 전달하는지 알아보자!

함수 전달

메서드가 아닌 그냥 "함수"를 전달하는 건 어렵지 않다.

그저 객체처럼 인수에 넣어서 잘 전달해주면 된다.

  • 캐싱 데코레이터

    기존에 만들어둔 함수가 시간이 오래 걸린다면,

    그 결과값을 캐싱해두는 래퍼 함수를 만들어 기존 함수를 재사용할 수 있다.

  function slow(x) {
    // CPU 집약적인 작업이 여기에 올 수 있습니다.
    alert(`slow(${x})을/를 호출함`);
    return x;
  }
  • 래퍼 함수의 또다른 예 : 딜레이
  function f(x) {
    console.log(x);
  }

  function delay(func, sec) {
    return function (str) {
      setTimeout(func, sec, str);
    };
  }

  // create wrappers
  let f1000 = delay(f, 1000);
  let f1500 = delay(f, 1500);

  f1000("test1"); // shows "test" after 1000ms
  f1500("test2"); // shows "test" after 1500ms

객체 메서드 전달

  • 문제는 객체 메서드의 전달이 어렵다
  • 객체 메서드는 객체라는 Context를 가진다. 따라서 아무런 설정 없이 메서드만 넘기게 되면,만약 메서드가 객체 context에 참조해야할 때 undefined한 상태이기 때문에 에러가 난다.
// worker.slow에 캐싱 기능을 추가해봅시다.
let worker = {
  someMethod() {
    return 1;
  },
  slow(x) {
    // CPU 집약적인 작업이라 가정
    alert(`slow(${x})을/를 호출함`);
    return x * this.someMethod(); // (*)
  },
};
  • cachingDecorator가 리턴하는 wrapper 함수의 this는 worker이지만,

    cachingDecorator(wrapper 함수) 인자로 worker.slow를 넘기면서 (func = worker.slow), functhis가 사라졌다. 따라서this 지정이 안된 slow를 호출하면 this.somemethod를 실행할 때 에러가 난다.

func.call()

  • 형식 : func.call(context, arg1, arg2, ...)
  • 메서드의 context를 고정하는 역할을 한다.
  • 앞에서 발생한 문제를 해결할 수 있다.

func.apply()

  • func.apply() func.call()과 거의 같은 기능을 한다.
  • 단지 인자값을 나머지 매개변수 문법을 사용해서 받는다.
  • 형식 : func.apply(context, args)

0개의 댓글