본문 바로가기

언어/JavaScript

함수 바인딩

반응형

코어자바스크립트를 필사한 것입니다.

 

사라진 this

객체 메서드를 콜백으로 전달할 때 this 정보가 사라지는 문제가 생긴다.

 

객체 메서드가 객체 내부가 아닌 다른 곳에 전달되어 호출되면 this가 사라진다.

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

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

this.firstName이 "John"이 되어야 하는데, 얼럿 창엔 undefined가 출력된다

이렇게 된 이유는 setTimeout에 객체에서 분리된 함수인 user.sayHi가 전달되기 때문이다.

위 예시의 마지막 줄은 다음 코드와 같다.

let f = user.sayHi;
setTimeout(f, 1000); // user 컨텍스트를 잃어버림

브라우저 환경에서 setTimeout 메서드는 인수로 전달받은 함수를 호출할 때, this에 window를 할당한다. 따라서 위 예시의 this.firstName은 window.firstName이 되는데, window 객체엔 firstName이 없으므로 undefined가 출력된다.

객체 메서드를 실제 메서드가 호출되는 곳으로 전달하는 것은 아주 흔하다. 이 때 컨텍스트를 제대로 유지하려면 어떻게 해야할까? 

 

 

 

방법 1: 래퍼

가장 간단한 해결책은 래퍼 함수를 사용하는 것이다.

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

setTimeout(function() {
	user.sayHi(); // Hello, John!
}, 1000);

위 예시가 의도한 대로 동작하는 이유는 외부 렉시컬 환경에서 user를 받아서 보통 때처럼 메서드를 호출했기 때문이다.

 

방법 2: bind

모든 함수는 this를 수정하게 해주는 내장 메서드 bind를 제공한다.

기본 문법은 다음과 같다.

let boundFuc = func.bind(context);

func.bind(context)는 함수처럼 호출 가능한 '특수 객체(exotic object)'를 반환한다. 이 객체를 호출하면 this가 context로 고정된 함수 func이 반환된다.

 

따라서 boundFunc를 호출하면 this가 고정된 func를 호출하는 것과 동일한 효과를 본다.

아래 funcUser에는 this가 user로 고정된 func이 할당된다.

let user = {
	firstName: "John"
};

function func() {
	alert(this.firstName);
}

let funcUser = func.bind(user);
funcUser(); // John

 

반응형

'언어 > JavaScript' 카테고리의 다른 글

자바스크립트 객체(Object)  (0) 2021.06.18
프로토타입  (0) 2021.05.19
DOM 인터페이스와 테스팅  (0) 2021.05.14
DOM  (0) 2021.05.14
Document  (0) 2021.05.13