객체지향언어에는 this
라는 키워드가 대부분 존재합니다.
자바스크립트에도 this
가 존재하는데, 이는 다른 객체지향언어와는 다르게 동작합니다.
다른 언어들처럼 함수를 선언할 때 this
에 바인딩할 객체가 결정되는 것이 아니고, 함수가 호출되는 방식에 따라 동적으로 바인딩할 객체가 결정됩니다. 이는 자바스크립트 인터프리터가 코드를 실행하면서 생성하는 Execution Context에 기인합니다.
function foo() {
const a = 2;
this.bar();
}
function bar() {
console.log(this.a);
}
foo(); //undefined
위의 예시에서의 foo의 this
는 함수의 Lexical Scope가 아닌 Global Scope를 참조하고 있습니다.
이는 Global Scope가 foo의 Execution Context이기 때문입니다.
Execution Context에는 Variable Object, Scope Chain, 그리고 this 에 대한 정보를 저장합니다.
Execution Context는 함수 호출 시 새로 생성되며, 동시에 this
값을 정합니다. 함수가 호출될 때, ECMAScript는 Arguments List와 thisArg 객체를 전달한다. 이 때 아래의 과정을 통해 this
값을 결정합니다.
strict mode
에서 정의된 함수일 경우, this
는 thisArg가 된다.this
는 global Object가 된다.this
는 toObject(thisArg) 가 된다.this
값이 정해지지 않았다면, this
는 thisArg가 된다.call, apply, bind 모두 thisArg 수정함으로써 this
값을 바인딩하는 것입니다.
그렇다면, thisArg는 어떻게 결정되는 것일까? 이는 함수 호출 과정의 6번 단계와 관계가 있습니다.
Type(ref) 값이 reference 라면,
위의 과정만 봐서는 this
가 언제 어떻게 바인딩되는지 알기 어렵습니다. 그래서, 흔히 발생하는 케이스를 통해 간단한 규칙을 소개하겠습니다.
new
키워드와 함께 함수를 호출하면,this
는 아예 새로운 객체가 된다.function Person(age) {
console.log(this)
this.age = age
console.log(this)
}
const person = new Person(22)
// {}
// { age: 22 }
apply
, call
, bind
가 함수의 호출/생성에 사용되면, this
는 인수로 전달된 객체가 된다.function foo() {
console.log(this)
}
const obj {
value: 5
}
const example = foo.bind(obj)
example() // { value: 5 }
foo.call(obj) // { value: 5 }
foo.apply(obj) // { value: 5 }
obj.method()
와 같이 함수를 호출하면, this
는 obj
가 된다.const obj = {
value: 5,
print: function() {
console.log(this)
}
}
obj.print() // { value: 5, print: f }
this
는 전역 객체(브라우저에서는 window
)가 된다. 단,strict mode
에서는 undfined
가 된다.function foo() {
console.log(this);
}
//브라우저에서 호출되면
foo() // Window { stop: f, open: f, alert: f, ... }
// 이 규칙은 3번 규칙과 동일합니다. 객체의 메소드로 선언되지 않은 함수는 자동으로 전역 객체의 property가 됩니다.
// foo()와 같이 함수를 호출하는 것은, window.foo()로 해석됩니다.
this
값을 받는다.참고자료
이번 글도 잘 보고 갑니다~