본문 바로가기

JavaScript/JavaScript기초

[Javascript] 함수 바인딩

함수 바인딩

setTimeout과 같은 메서드를 이용하여 객체 메서드를 실행시킬 때 아래와 같이 this 의 컨텍스트를 잃어버림

let obj = {
	
    name:'park',
    printName(){
    	console.log('name: '+ this.name);
    }
}

setTimeout(obj.printName,1000);

 

이러한 이유는 setTimeout 에 obj에서 분리된 printName이라는 함수가 전달되기 때문임

 

setTimeout을 이용해 함수를 호출할 때 함수의 this는 window가 할당되므로 위의 호출한 함수의 this는 obj가 아니라 window가 되므로 this.name 프로퍼티의 값이 할당되지 않았음

 

래퍼

이러한 문제를 해결하기 위한 방안으로 첫번째는 래퍼함수를 사용

let obj = {
	
    name:'park',
    printName(){
    	console.log('name: '+ this.name);
    }
}

setTimeout(() => {
	obj.printName();
},1000);

 

 setTimeout이 호출한 함수는 래퍼 함수이고 래퍼 함수 내에서 외부 렉시컬 환경의 obj.printName 함수가 실행되었으므로 컨텍스트가 변경되지 않음

 

하지만 래퍼를 이용한 방식의 문제점은 setTimeout에서 설정한 시간이 지나기 전에 객체를 변경하면 변경된 객체를 호출하게 됨

let obj = {
	
    name:'park',
    printName(){
    	console.log('name: '+ this.name);
    }
}

setTimeout(() => {
	obj.printName();
},1000);
obj.printName = () =>{ console.log("함수 변경됨") }

 

변경된 함수가 실행됨

 

bind

위의 문제점을 해결하는 두번째 방법으로는 모든 함수에 내장되어있는 bind 메서드를 사용할 수 있음

 

func.bind(context)를 이용하면 함수의 this를 context로 고정할 수 있음

 

let obj = {
	
    name:'park',
    printName(){
    	console.log('name: '+ this.name);
    }
}

setTimeout(obj.printName.bind(obj),1000);
obj.printName = () =>{ console.log("함수 변경됨") }

 

this가 obj로 고정되고 중간에 바뀐 함수가 적용되지 않아 원하는 값이 출력됨

 

인수 bind

위에서는 context만 바인딩 시켰지만 bind 메서드를 이용하여 함수의 인수들도 바인딩 시킬 수 있음

function printNum(a,b){ console.log(`a: ${a} , b: ${b}`) }

let argBind = printNum.bind(null,10); // printNum의 첫번째 인수를 10으로 바인딩

console.log(argBind(20));
console.log(argBind(30));

위 함수의 첫번째 인수를 10으로 바인딩 시켰으므로 a의 값은 10으로 고정되고 argBind를 통해 전달되는 인수는 2번째 인수인 b인것을 볼 수 있음

 

참조: https://ko.javascript.info/bind