본문 바로가기

Javascript

자바스크립트 - this keyword에 대해

728x90
this 키워드란
모든 실행컨텍스트(즉, 모든 함수)에서 생성되는 특수한 변수로, 해당 함수의 "소유자"의 값을 가지는 변수입니다. 

this 키워드의 특징은, 값이 유동적이라는 것입니다. 함수가 어떻게 호출되냐에 따라 달라지며

또한 함수가 실제로 호출되어야만 값이 할당됩니다. 아래에서 더욱 자세히 설명하겠습니다.

 

함수를 호출하는 데에는 4가지 방법이 있습니다.

 

 

1. 메서드로 호출

 

객체를 만들고, 객체에 붙어있는 함수를 호출하는 방법입니다.

만약 메서드로 호출하게 되면, this 키워드는 해당 객체를 가리킬것입니다.

const overaction = {
     name: 'overaction',
     food: 'apple',
     printFood: function() {
     	return this.food;
     }
 }

예를들어 위의 overaction 이라는 객체 안에

printFood 라는 메서드를 호출하는데 this가 보입니다. 이 this의 값은 무엇일까요?

 

앞에서 말한것처럼 해당 객체를 가리키기 때문에 overaction 객체가 값으로 들어가있고

this.food는 apple이 될 것입니다.

 

2. 그냥 함수로 호출

앞의 예제처럼 객체에 붙어있는 함수가 아닌 그냥 함수를 정의해서 호출하는 방식입니다.

이럴 경우 this 키워드의 값은 심플하게 undefined 가 됩니다.

물론 이것은 strict 모드에서만 그럴것이며 만약 strict 모드를 사용하지 않는다면 브라우저의 window 객체를

가리키게 될 것입니다. 이런 점은 코딩을 하다보면 심각한 문제가 될 수 있기때문에

반드시 strict 모드를 사용해야하는 또다른 이유입니다.

 

3. 화살표 함수로 호출

화살표함수는 기본적으로 this 키워드를 갖고있지 않다고 앞선 포스팅에서 이야기했습니다.

다만 this 키워드를 사용할 경우 감싸고있는 부모 함수의 this 키워드를 사용하기 때문에

"lexical this keyword" 라고 부르기도 합니다.

 

4. Event listener로써 호출

이 경우에는 해당 핸들러 함수가 가리키는 DOM element를 가리키게 됩니다.

 

 

4가지 경우로 따져본 this keyword의 특징으로는, 절대 해당 함수나 함수의 variable environment를 가리키지 않는다는 것입니다.

 

그리고 저 4가지 방법 말고도 new,apply,call,bind 메서드를 사용하는 방식도 있지만 나중 포스팅에서 다루도록 하겠습니다.

 

 

여러가지 방식에 대한 this 키워드 예시

아무것도 없는 상태에서 this 키워드를 출력하는 경우

console.log(this);

전역 스코프의 값인 window 객체가 값으로 출력됩니다.

 

함수를 호출했을 경우

const calcAge = function() {
  console.log(this);
}

calcAge();

앞에서 본 것처럼 undefined 값을 출력합니다.

strict 모드에서의 출력값이며 반드시 strict 모드를 사용한다고 가정하고 진행하고있습니다.

 

그렇다면 화살표함수를 호출했을 시 어떤 값을 가질까요?

const calcAge = () => {
  console.log(this);
}

calcAge();

 

화살표함수는 this 키워드를 가지고있지 않고, lexical this 키워드를 가진다고 했습니다.

따라서 함수의 부모 스코프는 전역 스코프이기 때문에 window 객체를 출력하게 됩니다.

일반적인 함수는 this 키워드의 값이 undefined지만 제대로 this 키워드를 가지고 있는 반면,
화살표함수는 부모 스코프의 this 키워드 값을 가집니다.

 

객체에서 함수를 복사해서 호출했을 경우

윗 부분에서 this 키워드는 값이 유동적이라고 했는데, 그 예시를 들어보겠습니다.

객체 하나를 만들고, 그 안의 함수를 복사해서 호출해보겠습니다.

함수 역시 하나의 값이기 때문에 대입할 수 있습니다.

const first = {
  firstName: 'over',
  calcAge: function () {
    console.log(this);
    console.log(this.firstName);
  }
}

const last = {
  firstName: 'action',
}

last.calcAge = first.calcAge;

last.calcAge();

복사해서 호출했더니 this 키워드 역시 복사한 last 객체를 가리키고있습니다.

 

객체에서 화살표 함수를 사용해서 호출했을 경우

'use strict';

const overaction = {
    first: 'over',
    food: 'apple',

    greet: () => console.log(`Hey ${this.first}`),
}

overaction.greet();

화살표함수는 this 키워드가 없고, 부모 스코프의 this 키워드를 사용한다고 했었습니다.

다만 여기서 헷갈리는 것은 greet 함수의 부모 스코프가 overaction 객체가 아니냐는 것인데,

이것은 객체를 정의하는 방식일 뿐이며 블록스코프라고 볼 수 없습니다.

따라서 부모 스코프는 전역 스코프가 됩니다.

결과

만약 따로 this를 출력한다면 window가 출력될 것입니다.

※ 객체 메서드로는 항상 일반 함수를 사용하는 것이 좋습니다

728x90