this
실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장된다. 실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우 this에는 전역 객체가 저장된다. 그 밖에는 함수를 호출하는 방법에 따라 this에 저장되는 대상이 다르다.
다른 대부분의 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체를 의미한다. 클래스에서만 사용할 수 있기 ㄸ애문에 혼란의 여지가 없거나 많지 않다. 그러나 자바스크립트에서의 this 는 어디서든 사용할 수 있다. 상황에 따라 this 가 바라보는 대상이 달라지는데, 어떤 이유로 그렇게 되는지를 파악하기 힘든 경우도 있고 예상과 다르게 엉뚱한 대상을 바라보는 경우도 있다.
! 상황에 따라 달라지는 this
자바스크립트에서는 기본적으로
실행 컨텍스트가 생성될 때 this 가 함께 결정된다.
함수를 호출 할 때 실행 컨텍스트가 생성된다.
그러므로 함수를 호출할 때 this가 결정된다.
! 전역공간에서 this
전역 공간에서 this 는 전역 객체를 가리킨다. 개념상 전역 컨텍스트를 생성하는 주체가 전역 객체이기 때문이다.
console.log(this); // Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
console.log(window); // Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
! 메서드로서 호출될 때 this
어떤 함수를 메서드로서 호출할 때 그 함수의 this 는 해당 메서드를 호출한 객체를 가리킨다.
var obj = {
method: function () {
console.log(this);
}
}
console.log(obj); // {method: ƒ}
obj.method(); // {method: ƒ}
! 함수로서 호출될 때 this
var func = function (x) {
console.log(x, this);
}
func(10); // 10 Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
! 내부함수의 this
var obj = {
method: function () {
console.log(this);
var innerFunc = function (x) {
console.log(x, this);
}
innerFunc(100);
}
}
console.log(obj); // {method: ƒ}
obj.method(); // {method: ƒ} 100 Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
내부함수를 실행시켜도 전역 객체가 this 에 바인딩 된 것을 확인할 수 있다.
- 기본적으로 함수로서 호출하는 경우의 this 는 전역 객체가 바인딩 된다.
- 메서드로서 호출하는 경우는 해당 메서드를 호출한 객체(해당 함수의 . 앞의 객체)가 this 에 바인딩 된다.
(eg. obj.method() 에서 obj 가 this 에 바인딩 된다. (점 앞에 있으므로))
(eg. obj1.obj2.obj3.method() 에서는 당연히 obj3 가 this 에 바인딩 됨))
! this 를 우회하는 방법 ( 함수로서 호출된(호출 주체가 없는) 녀석에게 전역 객체가 아닌 this 를 사용하게 하는 방법 )
var obj = {
method: function () {
console.log(this);
var that = this;
var innerFunc = function (x) {
console.log(x, that);
}
innerFunc(100);
}
}
console.log(obj); // {method: ƒ}
obj.method(); // {method: ƒ} 100 {method: ƒ}
this 를 변수에 할당하고, 함수를 선언할 때 this 대신 쓰고 싶은 this 를 할당해 놓은 변수(여기서는 that)를 사용 한다.
- ES5 까지는 이렇게 사용했으나 그 이 후에는 this 를 사용자가 할당할 수 있도록 하는 메소드가 나옴.
! this 를 바인딩 하지 않는 함수
ES6 에서 주로 쓰는 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this 를 그대로 활요할 수 있다. ( 바인딩 되지 않았다는 말은 함수 내부에서 사용할 this 가 없다. 즉 상위 스코프의 this 를 가져와서 사용 )
var obj = {
method: function () {
console.log(this);
var innerFunc = (x) => {
console.log(x, this);
}
innerFunc(100);
}
}
console.log(obj); // {method: ƒ}
obj.method(); // {method: ƒ} 100 {method: ƒ}
! 콜백함수에서의 this
콜백함수에서는 그 함수를 호출한 함수가 정하기 나름이다. 흔히 알고 있는 콜백 함수에는 setTimeout 이나 addEventListener 등이 있다.
setTimeout(function () { console.log(this) }, 1); // Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
window.document.body.addEventListener('click', function() { console.log(this) } ); // <body>...</body>
setTimeout 은 전역객체가 나오고, addEventListener 은 body 가 나왔다.
함수어 어떻게 정의되어있는지에 따라 this 가 달라진다.
! this 를 명시적으로 바인딩하는 법
call, apply, bind
var func = function (a, b, c) {
console.log(this, a, b, c);
}
func(1,2,3); // Window.... 1 2 3
func.call({ x: 1 }, 4, 5, 6); // { x: 1 } 4 5 6
func.apply({ x: 1}, [4, 5, 6]); // { x: 1 } 4 5 6
func.bind({ x: 1})(4, 5, 6); // { x: 1} 4 5 6
! 마무리
늘 성립하는 규칙
- 전역 공간에서 this 는 전역 객체 (Window)를 참조한다.
- 어떤 함수를 메서드로서 호출한 경우 this 는 메서드를 호출한 주체를 참조한다. ( 점 앞의 객체 )
- 어떤 함수를 함수로서 호출한 경우 this 는 전역 객체를 참조한다. 내부함수도 마찬가지이다.
- 콜백 함수 내부에서의 this 는 해당 콜백 함수를 넘겨 받은 함수가 정의한 바에 따른다. 특별히 정의되지 않았다면 전역 객체를 참조한다.
- 생성자 함수에서 this 는 생성된 인스턴스를 참조한다.
call, apply, bind 메서드는 this 를 명시적으로 지정할 수 있다.
'Programming language > JavaScript' 카테고리의 다른 글
호이스팅(Hoisting) (0) | 2020.10.24 |
---|---|
async vs defer (외부 스크립트 파일 불러오기) (0) | 2020.10.23 |
[vue] axios 전역으로 사용하기 (0) | 2020.09.14 |
[Vue] Vuex 시작하기 전에... (0) | 2020.07.10 |