하나씩 알아가기

this의 명시적 바인딩(call(), apply(), bind() 메소드) 본문

자바스크립트

this의 명시적 바인딩(call(), apply(), bind() 메소드)

clearwater 2021. 1. 21. 22:59
728x90
반응형

틀린 부분이 있을 경우, 지적해 주시면 감사하겠습니다.

 

명시적 바인딩(explicit binding)

함수 레퍼런스 프로퍼티를 객체에 넣지 않고 어떤 객체를 this 바인딩에 이용하겠다는 의지를 코드에 명확히 밝힐 방도는 없을까?

call(), apply() 메소드에 대해 알아보겠습니다. 두 메소드는 this에 바인딩 할 객체를 첫째 인자로 받아 함수 호출 시 이 객체를 this로 세팅합니다. this를 지정한 객체로 직접 바인딩 하므로 이를 '명시적 바인딩(explicit binding)이라고 합니다.

 

function foo() {
	console.log(this.a);
}

var obj = {
	a: 2
}

foo.call(obj);

foo.call()에서 명시적으로 바인딩하여 함수를 호출하므로 this는 반드시 obj가 됩니다.

 

이번에는 apply() 메소드를 살펴보겠습니다. 기본적으로 하는 역할은 동일합니다.

다만, apply()의 경우 두번째 인자를 배열 형태로 전달하는 것에 차이가 있습니다.

 

foo.call( obj, 'arg1', 'arg2', ... );

foo.apply( obj, ['arg1', 'arg2', ... ]);

function foo(something) {
	console.log(this.a, something);
	return this.a + something;
}

var obj = {
	a:2
}
var bar = function() {
	return foo.apply(obj, arguments);
}

var b = bar(3); // 2 3
console.log(b); // 5

bar에 함수 표현식을 사용하였는데 이 때 함수 내부에서 foo.apply(obj, arguments)로 foo를 호출하면서 obj를 this에 강제로 바인딩하였습니다. 따라서 bar를 어떻게 호출하든 이 함수는 항상 obj를 바인딩하여 foo를 실행합니다. 이런 바인딩을 '하드 바인딩'이라고 합니다.

 

추가로 ES5에 추가된 bind() 메소드도 알아보겠습니다.

function foo(something) {
	console.log(this.a, something);
	return this.a + something;
}

var obj = {
	a: 2
};

var bar = foo.bind(obj);

var b = bar(3); // 2 3
console.log(b); // 5

bind() 역시 기능적으로는 call(), apply()와 비슷합니다.

그런데 bind() 메소드는 함수를 호출하는 두 메소드와는 다르게, 주어진 this 콘텍스트로 원본 함수를 호출하도록 하드 코딩된 새 함수를 반환합니다.

 

그런데 예외가 있습니다.

call, apply, bind 메소드에 첫번째 인자로 null 또는 undefined를 넘기면 this 바인딩이 무시되고 기본 바인딩 규칙이 적용됩니다.

function foo(){
	console.log(this.a);
}

var a = 2;

var obj = {
	a: 3
}

foo.call(null); // 2
foo.call(obj); // 3

foo.call(null)로 호출할 시, 기본바인딩 규칙이 적용되서(비엄격 모드일 경우, 브라우저에서 기본 바인딩 규칙은 this가 window 객체를 가리킵니다) 2를 호출합니다.

 

 

 

 

참고 및 출처

You Don't Know JS [카일 심슨]

728x90
반응형