객체 this 바인딩 -5

lee jae hwan·2022년 7월 29일

javascript

목록 보기
60/107

지금까지 함수내 this를 바인딩하는 방법

  • 래퍼함수
  • bind함수
  • 화살표함수

위 방법들의 공통점은 콜백과 같이 this가 있는 함수를 전달해야 사용하는 방법이다.


데코레이팅함수
함수를 전달받아 추가기능을 확장한 함수를 반환한다.

데코레이팅함수에 this를 가진 함수를 전달할때 발생하는 문제점들을 알아보자


defer 데코레이팅함수는 전달된 함수를 1초후에 호출하는 함수를 반환한다.

function defer(f, ms) {
  return function(...args) {
    setTimeout(() => f(args), ms);
  };
}

let user = {
  age:34,
  sayAge(str){
    console.log(str+' '+this.age);
  }
};
user.sayAge = defer(user.sayAge,1000);
user.sayAge('hello');

user.sayAge가 this를 가지고 있기 때문에 값으로 전달하면 이벤트루프에의해 호출될때 전역객체로 호출되어 정상적인 결과를 얻을 수 없다.

래퍼함수로 전달할때

function defer(f, ms) {
  return function(...args) {
    setTimeout(() => f(args), ms);
  };
}

let user = {
  age:34,
  sayAge(str){
    console.log(str+' '+this.age);
  }
};
user.sayAge = defer((...args)=>user.sayAge(...args),1000);
user.sayAge('hello');

래퍼함수로 전달하면 호출인자도 감안해야하는 단점이 있다.

그외 치명적인 문제점이 발생한다.

데코레이터에 전달되는 함수가 래퍼함수이기 때문에 데코레이팅전 메소드의 참조를 가지고 있지 않는다는 것이다.

이렇게 되면 1초후에 호출되는 함수는 데코레이팅된 함수가 다시 호출되는 것이다.

let fn = defer((...args)=>user.sayAge(...args),1000);
fn('hello');

덮어쓰지 않고 새로운 반환함수를 사용해야 한다.

래퍼함수전달은 데코레이팅에 적합하지 않다.



바인딩메소드 전달할때

function defer(f, ms) {
  return function(...args) {
    setTimeout(() => f(args), ms);
  };
}

let user = {
  age:34,
  sayAge(str){
    console.log(str+' '+this.age);
  }
};
user.sayAge = defer(user.sayAge.bind(user),1000);
user.sayAge('hello');

바인딩된 함수를 값으로 전달하기 때문에 호출도 간편해진다.

하지만 바인딩은 함수유연성을 없애는 단점이 발생한다.


화살표함수

function defer(f, ms) {
  return function(...args) {
    setTimeout(() => f(args), ms);
  };
}

let user = {
  age:34,
  sayAge:(str)=>{
    console.log(str+' '+this.age);
  }
};
user.sayAge = defer(user.sayAge,1000);
user.sayAge('hello');

sayAge메소드를 화살표함수로 선언하면 객체생성시 this가 전역객체로 바인딩되기때문에 정상적인 결과를 얻을 수 없다.





콜포워딩방법

콜포워딩방법은 바인딩안된 메소드를 바인딩하면서 호출하는 방법이다.

function defer(f, ms) {
  return function(...args) {
    setTimeout(() => f.apply(this,args), ms);
  };
}

let user = {
  age:34,
  sayAge(str){
    console.log(str+' '+this.age);
  }
};
user.sayAge = defer(user.sayAge,1000);
user.sayAge('hello');

바인딩안된 user.sayAge를 값으로 전달하므로 함수유연성이 유지된다.

Function.prototype.apply메소드는 this를 바인딩하고 배열로 추가인자도 전달하면서 호출하는 기능을 제공한다.

this를 어떤 객체로 바인딩해야 하는가?

setTimeout(() => f.apply(user,args), ms);
객체를 user로 지정하면 데코레이터는 다른 객체메소드에 재사용할 수 없다.

f내 this를 바인딩할 객체는 user객체임이 분명한데 식별자를 user로 사용할 수 없다.

반환함수를 호출하는 컨텍스트는 무엇인가?
만약 user가 된다면 this식별자로 f내 this를 바인딩할 수 있다.

user.sayAge = defer(user.sayAge,1000); 와 같이 반환함수를 user.sayAge로 다시 할당되기때문에 f.apply(this,args)와 같이 this로 바인딩할 수 있는 것이다.

this를 this로 바인딩하는 기법을 기억하자

0개의 댓글