자바스크립트로 개발하다보면 무조건 만나는 this
항상 헷갈리고 어설프게 알고 있는 것 같아 연휴 맞이 정리를 하려고 한다.
대부분의 this
의 경우 함수를 호출한 방법에 의해 결정되며
실행중에는 새로 할당할 수 없고 함수를 호출할 때마다 다를 수 있다.
ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입
ES6 부터는 this
바인딩을 제공하지 않는 화살표 함수
를 추가했다.
전역 실행 컨텍스트에서 this
는 전역 객체를 참조
console.log(window ==== this); //true;
a = "cafe";
this.b = "coffee";
console.log(window.a); //cafe
console.log(window.b); //coffee
console.log(b); //coffee
단순 호출
엄격모드에서 this
값은 실행 문맥에 진입하여 설정되는 값을 유지한다. 엄격모드가 아닐 때는 기본값으로 브라우저에서는 window
인 전역 객체를 참조한다.
function f1() {
return this;
}
f1() === window; //true;
function f2() {
"use strict"
return this;
}
f2() === undefined; //true
this
의 값을 한 문맥에서 다른 문맥으로 넘기려면 call()
이나 apply()
를 사용해야 한다.
call
또는 apply
의 첫 번째 인자로 객체가 전달될 수 있으며 this
가 그 객체에 묶인다.
let obj = { a : "Custom" };
let a = "Global;
function whatsThis() {
return this.a;
}
whatsThis(); //"Global;
whatsThis.call(obj); //"Custom"
whatsThis.apply(obj); // "Custom"
bind()
f.bind(someObj)
를 호출하면 f와 같은 코드와 범위를 가졌지만 this
는 원본 함수를 가진 새로운 함수가 생성된다. 새 함수의 this
는 호출방식과 상관없이 영구적으로 bind()
의 첫번째 매개변수로 고정된다. 그리고 bind는 한번만 동작한다!
function f() {
return this.a;
}
let g = f.bind({a : "a"});
console.log(g()); //a
let h = g.bind({a : "aa"});
console.log(h()); //a
화살표 함수
화살표 함수에서 this
는 자신을 감싼 정적 범위 lexical context
이다.
전역 코드에서는 전역 객체를 가리킨다.
화살표 함수를 call, bind, apply
를 사용해 호출해 this
의 값을 정해주더라도 무시한다.
let globalObj = this;
let foo = (() => this);
console.log(foo() === globalObj); //true;
객체의 프로토타입 체인에서의 this
mdn 문서를 보면서 흥미로웠던 부분
let o = {
f: function() { return this.a + this.b }
}
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); //5
생성자로서
함수를 new
키워드와 함께 생성자로 사용하면 this
는 새로 생긴 객체에 묶인다.
function C() {
this.a = 37;
}
let o = new C();
console.log(o.a); //37
function C2() {
this.a = 37;
return {a : 38};
}
o = new C2();
console.log(o.a); //38
참고 : MDN This