본문 바로가기

Javascript

[애플코딩] 자바스크립트 this란 무엇인가?

자바스크립트에서 사용하는 this라는 키워드는 4가지 뜻을 가지고 있다. 

 

1)window :

먼저 window이다. 전역에서 this키워드를 출력해보면 콘솔에 window가 출력되는 것을 알 수 있다. 

이 키워드를 또 함수안에서 사용해도 this는 window라는 값을 출력한다. 

그런데, 만약에 여기에 use strict모드를 사용하면, 함수 안에서의 this는 undefinded를 출력하게 될 것이다. 

use strict모드는 문법적으로 조금 더 엄격한 모드를 말한다.

    <script>
        'use strict'

        console.log(this)

        function 함수() {
            console.log(this);
        }

        함수()
    </script>

 

2)object :

두 번째 this의 뜻은 그 자체의 오브젝트를 뜻한다. 아래와 같이 하나의 오브젝트 안에, 함수를 넣어놓고, 그 함수 안에 this를 출력한 경우 이 this는 자신이 속해 있는 객체를 출력한다. 

    <script>
        console.log(this)

        var 오브젝트 = {
            data : 'Kim',
            함수 : function(){
                console.log('안녕')
            }
        }

        오브젝트.data;
        오브젝트.함수() 

    </script>

조금 더 풀어서 말하면 오브젝트 내 함수안에서 쓰면 그 함수를 가지고 있는 오브젝트를 뜻한다. 

 

 

만약, 아래와 같이 객체 안에 또 다른 객체를 만들어서, 그 객체 안에서 this를 출력하는 함수를 만들면 어떻게 될까? 

    <script>
        //this의 첫번째 뜻은 window이다. 
        console.log(this)

        var 오브젝트 = {
            data : {
                함수 : function() {
                    console.log(this);
                }
            }
        }

        오브젝트.data;
        오브젝트.data.함수() 

    </script>

data라는 객체를 출력한다. this는 자신을 포함하고 있는 가장 가까운 객체를 출력한다. 

 

 

그런데, 만약에 신 문법인 화살표함수를 사용하는 경우에는 함수 바깥에 있는 그대로 가져다 사용한다. 결과적으로 아래와 같이 작성한 경우에 window라는 값을 출력한다. 

        var 오브젝트 = {
            data : {
                함수 : () => {
                    console.log(this);
                }
            }
        }

 

지금까지 1번 2번을 설명했는데, 사실 똑같은 의미이다. 전역에서 this를 출력하나, 객체 안에서 this를 출력하나 가장 가까운 공간 안에서의 객체를 출력하는 것이다. 

 

전역에서 this를 선언했을 때의 경우에는 , 우리가 여러 함수나 변수를 전역공간에 만들었을 때 window에 보관된다는 사실을 알 수 있다. 

이 window를 전역변수 보관소라고 부를 수 있다. 우리가 함수를 전역에 만들었으면, window라는 객체 안에서 함수를 만들었다고 생각하면된다. 

 

전역에서 this를 출력하면 그냥 window가 나옵니다 라고 말하면 98%만 맞은 것이다. 자신을 포함하고 있는 객체를 출력하는데 그게 window여서 그것을 출력한다고 말하면 더 정확하다. 

 

 

3)기계(constructor) 안에서 쓰면 새로 생성되는 오브젝트를 뜻함 : 

this의 세번째 의미는, constructor를 생성할 때, 사용된다. 하나의 함수안에서 this를 사용하면, 그것의 constructor를 생성한다. 이 constructor는 반복해서 객체를 찍어내주는 기계라고 생각하면 된다. 

this를 통해서 constructor를 생성했다면, 이것을 어떻게 뽑아낼까? 새로운 변수를 만들고 거기에 new 기계()라는 키워드를 생성하면 된다. 그러면 기계로부터 새로운 객체값, 그러니까 인스턴스를 생성할 수 있게 된다. 

    <script>

        function 기계 () {
            this.이름 = 'Kim';//이 this는 새로 생성되는 오브젝트(instance)를 뜻한다.
        }
        var 오브젝트 = new 기계(); //이렇게 출력하면 {이름 : 'Kim'}이라는 객체 값이 출력된다. 

    </script>

 

 

4)이벤트리스너 : 

이벤트 리스너 안에서 this를 사용하면, 이것은 e.currentTarget이라는 뜻으로 사용된다.  e.currentTarget를 사용하려면 본래, 파라미터로 e를 넘겨줘야 한다. 

    <script>

        document.getElementById('버튼').addEventListener('click', 
        function(){
            this; //e.currentTarget이라는 뜻으로 사용될 수 있다. 
        })

    </script>

 

 

그런데, 특이 케이스가 있다.  

case1. 이벤트리스너 안에서 콜백함수를 쓴다면 this는 ? : 

함수 안에 함수를 넣은 것을 콜백함수라고 부른다. 파라미터 안에 들어간 함수를 콜백함수라고 부르는데, 함수를 순차적으로 사용하고 싶을 때 사용한다고 생각하면 된다.

그런데, 지금 이 콜백함수 안에서 this를 출력하면 어떻게 될까? 

document.getElementById('버튼').addEventListener('click', function(e){
  var 어레이 = [1,2,3];
  어레이.forEach(function(){
    console.log(this)
  });
});

이렇게 출력하면 window가 나온다. 우리는 항상 this의 의미를 구분하려고 할 때, 이 함수가 쓰인 위치가 어딘지를 확인해야 한다. 이 함수가 쓰인 위치에 따라서 this의 값은 변하게 되어있다. 지금 상황에서 이 this는 그냥 일반함수 안에서 쓰였다고 생각하면 된다. 그렇기 때문에, 그냥 window를 출력하는 것이다. 현재의 함수는 엄밀히 말하면 전역함수라고 생각하면 된다. 

 

 

 

case 2. 오브젝트 안에서 콜백함수를 쓴다면 this는? 

 

이 상황에서 this를 출력하면 어떤 값이 나올까?

var 오브젝트 = {
  이름들 : ['김', '이', '박'];
  함수 : function(){
      오브젝트.이름들.forEach(function(){
        console.log(this)
      });
  }
}

이 값은 window를 출력한다. 왜 window가 나오는 것일까? 콜백에 들어가 있는 함수를 보면 이 함수는 근본이 없는 함수이다. 그냥 일반 함수이다. 이 친구를 포함하고 있는 객체인 window를 출력한다.  만약 함수라는 키값 안에서 this를 다시 출력하면 어떻게 될까? 오브젝트를 출력하게 될 것이다. 

this의 바로 위에 있는 함수가 무엇인지를 생각해보면, this의 의미를 알 수 있다. 

 

 

case 3.arrow function 안에서의 this는? :

arrow function의 특징이 있다면, 내부의 this값을 변화시키지 않는다. this값을 그냥 위에 있는 this값을 그대로 가져다 쓰게 된다. 아래의 경우 this값은 오브젝트가 된다. 

var 오브젝트 = {
  이름들 : ['김', '이', '박'];
  함수 : function(){
      오브젝트.이름들.forEach(() => {
        console.log(this)
      });
  }
}

이게 에로우 함수의 장점이라고 할 수 있다. this값을 변화시키지 않고, 그대로 사용하려고 할 때 에러우 함수를 사용하면 된다. 

 


애플코딩이라는 강의를 듣고 메모한 글입니다. 굉장히 좋은 강의라고 느끼면서 노트를 해나가는 중입니다. 자바스크립트의 심화된 버전을 공부하고 싶은 분들에게 추천합니다.