본문 바로가기
Archive

함수 바인딩

by livemehere 2022. 9. 1.

함수는의 this는 실행시점에서 결정된다.

쉽게말하면 obj.function() 이렇게 호출될때 결정되는데, dot 앞의 객체가 this가 된다.

그런데 만약 콜백으로 함수자체를 전달해버리면 this가 사라지는 문제가 발생한다.

 

setTimeout의 독특함

setTimeout함수는 특별하게 동작하는데, 전달받은 함수를 호출할때 this에 window를 할당하고, node에서는 타이머 객체에 할당한다.

그러므로 본 함수의 내부적으로 this는 엉뚱한 객체를 가르키게 되는것이다.

 

 

아래의 코드를 봤을때, user객체를 참조할 것 같지만, 내부의 sayHi()만이 전달된 상황이라 context를 잃어버리게 된다.

let user = {
  firstName: "John",
  sayHi() {
    alert(`Hello, ${this.firstName}!`);
  }
};

setTimeout(user.sayHi, 1000); // Hello, undefined!

 

그래서 보통은 이런식으로 콜백을 한번 더 감싸서 해결하는 방법도 있긴 하다.

이는 외부 렉시컬 환경에서 user 를 받아서 보통때와 같이 호출 했기 때문이다.

let user = {
    firstName: "John",
    sayHi() {
        console.log(`Hello, ${this.firstName}!`);
    }
};

setTimeout(()=>user.sayHi(), 1000); // Hello, John!

 

 

하지만 위의 방법은 만약 객체가 그사이에 변경된다면 호출시점에 기대한 객체가 아니게 되는 문제가 있다.

let user = {
  firstName: "John",
  sayHi() {
    alert(`Hello, ${this.firstName}!`);
  }
};

setTimeout(() => user.sayHi(), 1000);

// 1초가 지나기 전에 user의 값이 바뀜
user = { sayHi() { alert("또 다른 사용자!"); } };

// setTimeout에 또 다른 사용자!

bind

모든 함수는 this를 수정하게 해주는 내장메서드 bind를 가지고있다

call, apply와 마찬가지로 context를 첫번째 인자로 전달하고, 이후로는 인자를 전달한다.

let user = {
    firstName: "John",
    sayHi() {
        console.log(`Hello, ${this.firstName}!`);
    }
};

let myfnc = user.sayHi.bind(user);

setTimeout(myfnc, 100); // Hello, John!

 

이렇게 바인딩 하면, 함수와 context가 bound(묶인)상태가 되어 단독으로 호출할 수 있게되어, 확실하게 this가 고정된다.

let user = {
  firstName: "John",
  sayHi() {
    alert(`Hello, ${this.firstName}!`);
  }
};

let sayHi = user.sayHi.bind(user); // (*)

// 이제 객체 없이도 객체 메서드를 호출할 수 있습니다.
sayHi(); // Hello, John!

setTimeout(sayHi, 1000); // Hello, John!

// 1초 이내에 user 값이 변화해도
// sayHi는 기존 값을 사용합니다.
user = {
  sayHi() { alert("또 다른 사용자!"); }
};

 

Context가 아닌 인수 바인딩도 가능하다

자주 쓰이진 않지만 아래와같이 인수를 바인딩해버릴 수 도 있다.

function mul(a, b) {
  return a * b;
}

let double = mul.bind(null, 2);

alert( double(3) ); // = mul(2, 3) = 6
alert( double(4) ); // = mul(2, 4) = 8
alert( double(5) ); // = mul(2, 5) = 10

 

반응형

'Archive' 카테고리의 다른 글

클래스 문법  (0) 2022.09.03
prototype 과 상속  (0) 2022.09.01
call/apply 와 데코레이터, 포워딩  (0) 2022.09.01
잘안알려진 함수특성  (0) 2022.08.31
전역 객체  (0) 2022.08.31