함수라고 다같은 this가 아니여
Javascript에는 함수를 표현하는 데 여러가지가 있지만 크게 2가지 방식이 있다. 일반적으로 함수를 선언하는 방식과 화살표 함수로 간단히 표현하는 방식이 있다. 두 방식은 "this"를 참조했을 때 참조하는 값이 다르다. 간단히 살펴보자.
1. 화살표 함수
화살표 함수란, 아래와 같이 화살표 방식으로 선언하는 함수를 말한다. 보통 콜백함수에서도 사용하고 함수형 프로그래밍으로 표현할 수 있어서 많이 사용된다.
const myArrowFunction = () => {
console.log(this)
}
2. 함수 선언형 (일반 함수)
일반적으로 "function"으로 선언해서 함수를 선언하는 경우가 있다. 아래와 같은 형태이다.
function myFunction() {
console.log(this)
}
그럼, 다음과 같은 Object가 있다고 생각해보자. 각각에서 출력되는 this는 어떻게 다를까? 실제 브라우저 개발자 모드를 열어서, 아래 코드를 입력해서 결과물을 살펴보자.
let 테스트1 = () => console.log(this);
function 테스트2() {
console.log(this);
}
const MyObject = {
화살표형외부함수: 테스트1,
일반형외부함수: 테스트2,
화살표형내부함수: () => console.log(this),
일반형내부함수: function() {
console.log(this)
},
객체함수: function() {
let 내부화살표함수 = () => {
console.log(this)
}
내부화살표함수();
}
}
MyObject.화살표형외부함수(); // window 객체
MyObject.일반형외부함수(); // MyObject 객체
MyObject.화살표형내부함수(); // window 객체
MyObject.일반형내부함수(); // MyObject 객체
MyObject.객체함수(); // MyObject 객체
하나씩 살펴보자.
1. "화살표형외부함수"인 테스트1은 전역 스코프에 정의된 화살표함수이다. 화살표 함수는 자신만의 this를 가지지 않고, 정의된 곳의 외부 렉시컬 환경의 this를 사용한다. 따라서 this는 브라우저 환경의 this(window객체)가 나온 걸 볼 수 있다.
2. "일반형외부함수"인 테스트2는 전역 스코프에 정의된 일반 함수이다. 일반 함수의 this는 호출 방식에 따라 동적으로 결정된다. 따라서 MyObject의 메서드로 호출되었으므로, this는 MyObject를 가리킨다.
3. "화살표형내부함수"는 MyObejct 리터럴 내부에서 정의되었으나, 객체 리터럴은 새로운 스코프를 생성하지 않는다. 그래서 화살표 함수의 this는 객체 리터럴이 정의된 외부 스코프(여기서는 전역 스코프)의 this를 가리킨다. 그래서 브라우저의 전역 스코프의 this인 window가 출력되었다.
4. "일반형내부함수"는 일반 함수로 정의되었고 MyObject의 내부함수로 호출되었으므로 this는 MyObject를 가리킨다.
5. "객체함수"는 일반 함수로 정의되었고, 내부의 "내부화살표함수"는 자신을 감싸고 있는 "객체함수"의 this를 사용한다. 따라서 객체함수의 this는 MyObject이므로 MyObject가 출력된다.
이 차이점을 잘 알고 있어야될것같다. 이를 통해 콜백함수로 왜 화살표함수를 사용하는지도 잘 알 수 있다. 화살표함수는 자신만의 this를 만들지 않으므로, 외부 컨텍스트의 this를 참조해야 할 때 매우 유용하다.
이 예시에서 만약 인터벌의 콜백함수를 화살표 함수로 사용하지 않았다면 this가 Counter 인스턴스를 가리키지 않았을 것이고, 그러면 count에 접근하기 어려웠을 것이다.