ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 화살표 함수( Arrow Function )에서의 this 바인딩
    개발 2020. 4. 29. 23:14

     

     

    일반 함수는 앞서 블로깅 된 4가지의 규칙을 준수합니다. 즉, 일반 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정되는 것이었습니다.


    하지만 ES6부터는 이 규칙들을 따르지 않는 특별한 함수인 화살표 함수가 추가 되었습니다.

    화살표 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정됩니다. 동적으로 결정되는 일반 함수와는 달리 화살표 함수의 this 언제나 상위 스코프의 this를 가리키는 것입니다. 이를 Lexical this라 합니다.

     

     

    다음 예제는 화살표 함수의 렉시컬 스코프를 나타낸 예제입니다.

    function foo(){
      // 화살표 함수 return
      return (a) => {
        // 여기서 'this'는 어휘적으로 상위 스코프인 'foo()'에서 상속됩니다.
        console.log(this.a);
      };
    }
    
    let obj = {
      a : 2
    };
    
    let obj2 = {
      a: 3
    };
    
    let bar = foo.call(obj1);
    bar.call(obj2);  // 2

    foo() 함수 내부에서 생성된 화살표 함수는 foo() 호출 당시 this를 무조건 어휘적으로 상속 받습니다.

    foo()함수는 call() 메서드로 obj1에 this가 바인딩 되므로 변수 bar( return된 화살표 함수를 가리키는 변수 )의 this 역시 obj1로 바인딩 됩니다. 하지만 리턴된 화살표 함수를 담은 변수 bar를  bar.call(obj2)로 실행하여 obj2를 this로 바인딩하면 this.a는 3이 나올 것이라고 예상하겠지만 화살표 함수는 절대로 call과 같은 메서드로 this를 바인딩 할 수 없습니다!

    그렇기 때문에 bar.call(obj2)는 this가 바인딩 되지 않아 상위 스코프인 foo함수의 this를 상속받아 2를 출력하게 되는 것입니다.

     

     

    화살표 함수는 이벤트 처리기나 타이머 등의 콜백에 널리 쓰입니다.

    다음 예제를 통해 알아보겠습니다.

    function foo(){
      setTimeout(() => {
        // 여기서 'this'는 어휘적으로 'foo()'에서 상속됩니다.
        console.log(this.a);
      }, 1000);
    }
    
    let obj = {
      a: 2
    }
    
    foo.call(obj);  // 2

    화살표 함수는 this를 확실이 보장하는 수단인 bind()와 거의 유사한 역할을 합니다.

     

    이번에는 return 객체 안에 정의 된 메서드에 setTimeout을 넣어서 실행하였을 때의 this를 알아보겠습니다.

    function foo(){
      return {
        first: 'hyojin',
        last: 'lee',
        asyncFn: function(){
        
          console.log(this); // {first: "hyojin", last: "lee", setTimeFunc: ƒ}
          
          setTimeout(() => {
            console.log(this.first);
          }, 1000);
        }
      }
    }
    let bar = foo();
    bar.asyncFn();  // hyojin

    foo()라는 함수를 실행하면 객체를 리턴합니다. 리턴되는 객체 안에는 asyncFn() 라는 메서드가 있고 이 메서드는 1초 후에 this.first 를 출력하는 함수 입니다.

    변수 bar에 foo() 함수를 실행하여 return 되는 객체를 담았고, bar.asyncFn()를 실행하여 1초 후에 this..first 값인 'hyojin'을 잘 출력하는 것을 볼 수 있습니다.

     

    여기서 먼저 알아야 할 점은 setTimeout() 에서의 this는 항상 window를 가리킵니다. 

    왜냐하면 setTimeout()은 window.setTimeout이기 때문입니다. 실제로 저 화살표 함수를 일반 함수로 바꿔서 작성한다면 this.first값은 undefined를 출력할 것입니다. window에는 first라는 속성을 정의한 적이 없기 때문입니다.

     

    그런데 화살표 함수에서는 this.first를 잘 출력하고 있습니다.

    화살표 함수에서의 this는 언제나 상위 스코프의 this를 상속받는다고 하였습니다.

    setTimeout()의 상위 스코프인 asyncFn() 에서 console로 this 값을 출력해본 결과 리턴된 객체를 가리키고 있는 것을 볼 수 있고 setTimeout()의 콜백 함수로 작성한 화살표 함수는 상위 스코프의 this를 상속받아 리턴된 객체에서 first 속성을 찾아서 출력하는 것입니다.

     

     

    정리하기

    1. 화살표 함수는 항상 상위 스코프의 this를 상속받습니다.
    2. 화살표 함수는 bind(), call()과 같은 메서드로 this를 바인딩 할 수 없습니다.

    '개발' 카테고리의 다른 글

    Object.create()와 constructor  (2) 2020.05.11
    ES6 - class로 작성한 OOP  (0) 2020.05.08
    ES6 문법 - Arrow Function  (0) 2020.04.28
    Node.js 시작하기  (0) 2020.04.27
    call과 apply, bind 메서드를 이용한 명시적인 this 바인딩  (0) 2020.04.20
Designed by Tistory.