코어자바스크립트 강의정리 - 3. this
2강에서 배웠듯이 실행컨텍스트 안에는 VariableEnvironment, LexicalEnvironment, ThisBinding이 있다.
실행컨텍스트가 활성화 될때 ThisBinding을 한다는 것이고, 이는 함수가 호출될때 그제서야 this가 binding(연관, 세팅)된다는 것을 의미한다. 그렇기 때문에 함수를 어떻게 호출하느냐에 따라서 this가 가리키는 대상이 달라진다.
this가 달라지는 조건은 크게 5가지가 있다.
1. 전역공간에서
전역공간에서 this를 호출하면 window/global (브라우저에선 window, node에선 global) 을 가리킨다.
2. 함수 호출시
함수 호출시 this는 전역공간에서와 똑같이 window/global 전역객체를 가리킨다. 함수안에서 호출하는 함수 또한 마찬가지다. somgFunc(); 형태로 호출하는 함수의 this는 모두 전역객체이다. 이는 직관적으로 좀 이해가 가지 않을수 있는 부분이다. 함수 호출시 this를 사용하면 전역객체를 가리키는 것이 맘에 들지 않을 수 있다. 이럴때 사용할수 있는 우회법은 3. 매서드 호출시에서 추가로 설명한다.
ECMAScript 6 에서는 this를 바인딩하지않는 arrow function 을 통해 이 문제를 해결했다. arrow function은 애초에 this가 바인딩 되어있지 않기 때문에 arrow function 안에서 this를 사용하면 외부 렉시컬 범위에서 this를 찾아 사용한다.
3. 매서드 호출시
객체의 매서드로 호출될때는 조금 다르다. 예를들어
var a = {
b: function() {
console.log(this);
}
}
a.b();
는 코드가 있을때 출력값은 a 객체가 된다. 왜냐하면 매서드로 호출했을때의 this는 호출하는 함수를 제외하고 ' . ' 앞에 있는 객체가 this가 된다. 또 다른 예를들어 a.b.c( ) 와 같이 호출하면 a.b가 this가 된다. a['b'].c( ); 처럼 대괄호 표기법을 사용해도 this는 a.b 로 같다.
이를 응용하며 매서드 내부에서 또 함수를 호출하는 경우의 this도 제어할수 있다. 원래라면 매서드 내부에서 함수를 호출하면 매서드 안에서 호출했더라도 2. 의 조건때문에 this는 전역객체를 가리키겠지만. 매소드에 var self=this; 라는 식으로 this를 미리 저장해두고 매서드 내부함수는 this 대신 self(이름이 굳이 self가 아니어도 됨) 를 사용하면 우리가 원하는 결과를 얻을 수 있다. 그러나 2. 에서 설명했듯이 arrow function이 생긴 지금은 굳이 이렇게 할 필요가 없다. 그냥 신 문법 쓰면 된다.
4. callback 호출시
콜백 호출시에 대해 설명하기 전에 call, apply, bind를 이용한 명시적인 this 바인딩에 대해 잠깐 알고가자.
call, apply, this매서드는 this를 내맘대로 바인딩하여 함수를 호출하게 해준다.
a.call( thisArg, 나머지 인자들)
a.apply(thisArg, [나머지 인자들])
a.bind(thisArg, 나머지 인자들)
의 식으로 사용하고 call 과 apply는 나머지 인자들을 배열로 넘겨주냐 그냥 넘겨주냐의 차이만 있고 완전히 같다.
bind는 함수에 this를 바인드하고 호출하는 call, apply와 다르게 함수에 this를 바인드만 하고 호출하지는 않는다.
이제 콜백함수에서의 this를 알아보면 매서드 안에서의 콜백이던 뭐던 함수 호출형식으로 this를 사용하면 this는 전역객체를 가리킨다. 그러나 call, apply, bind 를 이용해 콜백함수에 명시적으로 this를 바인딩하면 콜백함수도 명시적으로 지정된 this를 사용한다. addEventListener처럼 미리 콜백함수에 this를 바인딩 해놓은 함수는 이때문에 콜백함수에서 this를 사용하면 전역객체가 아니라 addEventListener가 정의해놓은 (이벤트가 발생한 타겟 대상 엘리먼트) 요소를 this로 사용한다. 그런 경우에도
document.getElementById('a').addEventListener('click', function(){
console.dir(this);
}.bind(customThisObj)
);
와 같은 방법으로 내가 원하는 this를 다시한번 지정해 줄 수 있다.
5. 생성자함수 호출시
생성자 함수 호출( new 연산자 사용)시 에는 새로 만들 인스턴스 객체 그 자체가 곧 this가 된다.
function Person(n, a){
this.name=n;
this.age=a;
}
var roy= Person('재남', 30);
console.log(window.name, window.age); //재남 30
를 하면 생성자 함수 없이 그냥 함수로 Person을 호출했기 때문에 window 전역객체에 name과 age값이 담기게 된다.
(roy에는 아무 값도 담기지 않는다)
function Person(n, a){
this.name=n;
this,age=a;
}
var roy= new Person('재남', 30);
console.log(roy); //재남 30
그러나 new를 넣은채로 호출하면 this는 roy라는 인스턴스 그 자체를 this가 가리키게 되면서 roy.name은 재남 roy.age는 30 이 된다.
댓글을 작성해보세요.