this 바인딩
기본 바인딩(Default Binding)
function foo() {
const a = 10;
console.log(this.a);
}
foo(); // undefined
암시적 바인딩 (Implicit Binding)
const foo = {
a: 20,
bar: function () {
console.log(this.a);
}
}
foo.bar(); // 20
명시적 바인딩 (Explicit Binding)
const foo = {
a: 20,
}
function bar() {
console.log(this.a);
}
bar.call(foo); // 20
bar.apply(foo); // 20
const foo = {
a: 20,
}
function bar() {
console.log(this.a);
}
const bound = bar.bind(foo)
bound(); // 20
new 바인딩 (new Binding)
function Foo() {
this.a = 20;
}
const foo = new Foo();
console.log(foo.a); // 20
화살표 함수
const foo = {
a: 20,
bar: function () {
setTimeout(() => {
console.log(this.a);
}, 1);
}
}
foo.bar(); // 20
setTimeout의 콜백인 화살표 함수의 선언시에 this는 foo 객체를 가리키고 있기 때문에(렉시컬 스코프), 콜백이 실행될 때 this는 foo를 가리키게 된다.
화살표 함수로 선언시에 렉시컬 스코프를 통해 바인딩된 this는 apply, bind등의 함수나 new 함수로 오버라이드할 수 없다. 그렇기때문에 주로 콜백 함수로 사용할 때 유용하다.
apply, call, bind같은 바인딩 메소드, 또는 화살표 함수가 나오기 전에는 골치아픈 this 바인딩을 _this, that, self와 같은 렉시컬 스코프를 이용해서 해결하였다. 호출시 결정되는 this를 렉시컬 스코프를 이용해 선언시에 정해주는 효과를 주는 것이다.
~렉시컬 스코프란?
렉시컬 스코프란 중첩된 함수 그룹에서 내부 함수가 상위 범위의 변수 및 기타 리소스에 액세스 할 수 있음을 의미한다.
즉, 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정한다는 뜻이며, 가장 중요한 점은 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다는 것이다.
다른 말로, 정적 스코프(Static Scope)라 부르기도 한다.
var x=1;
function foo() {
var x=10;
bar();
}
function bar() {
console.log(x);
}
foo(); //1
bar(); //1
위 예제를 보듯 JS는 렉시컬 스코프를 따르기에 함수를 선언한 시점에 상위 스코프가 결정된다. 함수를 어디서 호출했는지는 스코프 결정에 아무런 영향을 주지 않는다. 위 예제의 bar 함수는 전역에 선언됐기에 bar 함수의 상위 스코프는 전역 스코프이고, 따라서 전역 변수 x의 값 1을 두번 출력한다.
참조:
[JS] 알쏭달쏭 자바스크립트 this 바인딩
[JS] 6. 함수 스코프 & 블록 스코프 & 렉시컬 스코프