자바스크립트에서 this라는 개념은 많이 헷갈린다. 그래서 오늘 정리 해볼려고 한다. 다른 객체지향언어에서는 대부분 this는 클래스로 생성한 인스턴스 객체를 의미한다. 하지만 자바스크립트에서의 this는 어디서든 사용을 할 수 있고, 상황에 따라 this가 바라보는 대상이 달라진다.
자바스크립트에서의 this를 한번 알아보도록 하자.
우선 전 글에서 확인할 수 있듯이
JS시리즈 - 실행 컨텍스트
실행컨텍스트에는
1. variableEnvironment
2. LexicalEnvrionent
3. ThisBinding
3가지로 크게 구성된다고 했다.
ThisBinding에는 현재 실행 컨텍스트가 참조하는 this에 대한 정보가 담기게 된다.
ThisBinding은 실행컨텍스트가 활성화 될때 한다.
실행컨텍스틑 언제 생성되는가? 바로 이 컨텍스트에 해당하는 함수가 호출 되는 순간이다.(전역컨텍스트 제외)
this는 바로 확인할 수 있는게 아니다.
함수를 호출한 방식에 따라서 this는 얼마든지 달라진다.
즉, 호출하는 방식에 따라 달라진다는 것이다.
this는 크게 5가지 상황에서 바라 볼 수 있다.
각각의 상황에서 this가 어떻게 다른지 확인 해보자.
console.log(this);
어떤 함수를 호출하는 것에는 여러가지 방법이 있지만,
일반적인 방법은 두가지가 있다.
함수로서의 호출
메서드로서의 호출
함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치로,
이 둘을 구분하는 유일한 차이는 독립성!
함수는 자체적으로 독립적인 기능을 수행한다.
메서드는 자신이 호출한 대상 객체에 관해서 동작을 수행
EX) 먼저 함수로서 호출, 메서드로서 호출
var 함수 = function(){
console.log(this);
}
함수(); // 브라우저 : window / Node.js : global
var obj = {
메서드: function(){
console.log(this);
}
};
obj.메서드(); // {메서드 : f}
그래서 위 코드 처럼 저런 결과를 출력하게 된다.
여기서 헷갈리는 부분이 있다. 바로 함수로서 호출할 때 그 함수 내부에서의 this 관련한 것이다.
위에서 말했듯이 함수로 호출을 한다면 this에는 전역 객체를 가리킨다고 설명하였다.
var 객체1 = {
바깥:function(){
console.log(this); // (1)
var 내부함수 = function(){
console.log(this); // (2) (3)
}
내부함수();
var 객체2 = {
내부메서드 : 내부함수
};
객체2.내부메서드();
}
};
객체1.바깥();
실행 결과를 예측해보자.
(1) : 객체1
(2) : 전역객체
(3) : 객체2
말그대로
여기서 저렇게 내부함수에서 함수를 호출하더라도 this는 전역객체를 가리키게 된다는 점에서 설계상의 오류라는 말이 많다.
그래서 ES6부터 this 바인딩을 하지않는 arrow function 즉, 화살표 함수가 나오게 되었고 바로 위 컨텍스트에 있는 this를 그대로 가져다 사용한다.
저 위의 코드에서 내부함수라는 함수를 화살표 함수로 바꿔보자.
var 객체1 = {
바깥:function(){
console.log(this); // (1)
var 내부함수 = () => {
console.log(this); // (2)
}
내부함수();
}
};
객체1.바깥();
출력 결과를 예상해보자.
콜백함수란?
콜백 함수도 함수이기 때문에 기본적으로 this는 전역객체를 참조하게 되지만, 제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조하게 됩니다.
제어권을 가진 함수가 콜백의 this를 지정해둔 경우도 있다.
setTimeout(function(){console.log(this)}, 1000); // (1)
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a')
.addEventListener('click', function(){
console.log(this); // (2)
});
(1) setTimeout 함수는 기본적으로 콜백 함수를 호출할 때 대상이 될 this를 지정하지 않는다. 따라서 콜백 함수 내부에서의 this는 전역객체를 참조하게 됩니다.
(2) addEventListener 메서드는 콜백 함수를 호출 할 때 자신의 this를 상속하도록 정의 되어 있기 때문에 앞서 지정한 엘리먼트가 this가 됩니다.
하지만 이러한 경우에서도 개발자가 this를 바인딩해서 콜백을 넘기면 그에 따른다.
생성자 함수란?
그럼 생성자 함수로 호출 시에는 this는 어떤것을 참조하게되는가?
var Dog = function(name, type){
this.bark = "멍멍";
this.name = name;
this.type = type
};
var 누렁이 = new Dog("누렁이", "진돗개");
var 뽀삐 = new Dog("뽀삐", "말티즈");
console.log(누렁이); // Dog { bark: '멍멍', name: '누렁이', type: '진돗개' }
console.log(뽀삐); // Dog { bark: '멍멍', name: '뽀삐', type: '말티즈' }
Dog 라는 변수에 익명 함수를 할당하고 이 함수 내부에서 this 접근한다음 프로피트에 각각의 값을 대입합니다.
여기서 this는 생성자 함수로 생성되는 누렁이 인스턴스, 뽀삐 인스턴스를 가리키는 것을 확인할 수 있습니다.
명시적으로 바인딩을 하지 않는 이상 5가지는 성립합니다.
여기서 한가지 의문점이 든다. 그럼 명시적으로 this를 바인딩을 하지 않는? 이말인 즉슨 명시적으로 this를 정할 수 있다라는 것이다. 이 주제에 대해서는 다음번에 알아보도록 하겠다.
참고 :
1. 코어자바스크립트
2. 인프런 - 코어자바스크립트