ES6 Arrow Function & This Test

18 Feb 2016

1. 글에 대해

  • 이 글은 ES5ES6 Arrow Function 안에서 this 값이 어떤식으로 평가되는지에 대한 내용을 다루고있다.

  • 또한 모든 결과는 Chrome 브라우저를 통해 테스트된 결과입니다.

2. ES5 & this

  • this 값 초기화 테스트

    ```javascript
    // A 함수 객체를 선언한다.
    function A() {
      
      
        function B() {
            // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
            console.log(this);  // global Object
        }
      
        // AO 에 포함된 내부 함수를 호출한다.
        B(); // AO.B();
          
        // 초기화된 this 값을 반환한다.
        return this;
    }
      
    // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
    console.log(A()); // global Object
      
    // this 는 생성된 인스턴스로 초기화된다.
    console.log(new A()); // A Object
      
    // this 는 null 로 초기화되며, null 은 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
    console.log(A.call(null)); // global Object
      
    // this 는 전달된 {x: 1} 객체로 초기화된다.
    console.log(A.call({x: 1})); // Object {x: 1}
      
    // this 는 전달된 {x: 2} 객체로 초기화된다.
    console.log(A.apply({x: 2})); // Object {x: 2}
      
    // this 는 전달된 {x: 2} 객체로 초기화된다.
    console.log(A.bind({x: 3})()); // Object {x: 3}
    ```
    
  • 바인딩된 익명 함수 내부에서의 this

    ```javascript
    // 버튼 객체를 생성한다.
    var btnElem = document.querySelector('#btn1');
      
    // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
    btnElem.addEventListener('click', function(){
      
        // 이 경우 this 값은 target element 인 btnElem 객체를 가리킨다.
        console.log(this); // btnElem object        
    });
    ```
    
  • bind 함수를 통해 (바인딩된)함수 내부 this 값을 전역 스코프의 this 값으로 초기화 시킬 수 있다.

    ```javascript
    // 버튼 객체를 생성한다.
    var btnElem = document.querySelector('#btn1');
      
    // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
    btnElem.addEventListener('click', function(){
      
        // 이 경우 this 값은 bind 함수를 통해 초기화된 this 값을 가리킨다.
        console.log(this); // global object
    }.bind(this));
    ```      
    
  • this 값 초기화 테스트 in Strict Mode

    • Strict Mode 에서는 this 값이 null, 또는 undefined 인 경우, 암묵적으로 global Object 로 변환되지 않는다.

        // A 함수 객체를 선언한다.
        function A() {
      
            // Strict Mode 선언
            'use strict';
      
            function B() {
                // this 는 undefined 로 초기화된다.
                console.log(this);  // undefined
            }
      
            // AO 에 포함된 내부 함수를 호출한다.
            B(); // AO.B();
      
            // 초기화된 this 값을 반환한다.
            return this;
        }
      
        // this 는 undefined 로 초기화된다.
        console.log(A()); // undefined
      
        // this 는 global object 로 초기화된다.
        console.log(this.A());
      
        // this 는 생성된 인스턴스로 초기화된다.
        console.log(new A()); // A Object
      
        // this 는 null 로 초기화된다.
        console.log(A.call(null)); // global Object
      
        // this 는 전달된 {x: 1} 객체로 초기화된다.
        console.log(A.call({x: 1})); // Object {x: 1}
      
        // this 는 전달된 {x: 2} 객체로 초기화된다.
        console.log(A.apply({x: 2})); // Object {x: 2}
      
        // this 는 전달된 {x: 2} 객체로 초기화된다.
        console.log(A.bind({x: 3})()); // Object {x: 3}
      
  • this 값 초기화 테스트 in Object

    • 객체 메서드에서의 this 는 해당 메서드를 내부 프로퍼티로 소유한 객체를 가리킨다.

        var A = {
            x: function(){
      
                var B = function(){
                    // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다.
                    console.log(this); // global Object
                }
      
                // AO 에 포함된 내부 함수를 호출한다.
                B(); // AO.B();
      
                // 초기화된 this 값을 반환한다.
                return this;
            }
        };
      
        // 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다.
        console.log(A.x()); // A Object
      

3. ES6 Arrow Function & this

  • Arrow Function 은 자신만의 this, arguments, super, new.target 이 할당되지 않는다.

  • Arrow Function 의 this 값은 함수가 위치한 지점을 둘러싼, 전역/함수 스코프this 값을 가리키며, 바인딩된 후 변하지 않는다.

          
      // global execution context
          
      // Arrow Function 을 할당한다.
      var A = () => {
          
          // A function execution context
          
          var B = () => {
              
              // B function execution context
                  
              // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
              console.log(this);
          }
          
          B();
          
          // 초기화된 this 값을 반환한다.
          return this;
      };
          
      // this 는 global object 로 초기화된 후 변하지 않는다. 
      console.log(A()); // global Object
          
      // this 는 global object 로 초기화된 후 변하지 않는다.
      console.log(this.A()); // global Object
          
      // new 연산자를 통해 새로운 인스턴스 생성 시 에러가 발생한다.
      try {
          console.log(new A());
      }
      catch(e){
          // Uncaught TypeError: () => this is not a constructor
          console.log(e.message);
      }
          
      // this 는 global object 로 초기화된 후 변하지 않는다.
      console.log(A.call(null)); // global Object
          
      // this 는 global object 로 초기화된 후 변하지 않는다.
      console.log(A.call({x: 1})); // global Object
          
      // this 는 global object 로 초기화된 후 변하지 않는다.
      console.log(A.apply({x: 2})); // global Object
          
      // this 는 global object 로 초기화된 후 변하지 않는다.
      console.log(A.bind({x: 3})()); // global Object
          
    
  • 바인딩된 익명 (Arrow)함수 내부에서의 this

      // 버튼 객체를 생성한다.
      var btnElem = document.querySelector('#btn1');
          
      // 생성된 버튼 객체에 click 이벤트를 바인딩한다.
      btnElem.addEventListener('click', () => {
          
          // 이 경우 arrow function 의 this 값은 해당 함수를 둘러싼 전역 스코프의 this 값으로 초기화된다.
          console.log(this); // global Object
              
          // 버튼 객체를 통해 명시적으로 접근한다.
          console.log(btnElem);
      });
    
  • 함수 객체 내부에서의 Arrow Functionthis

      function A(){
          
          // arrow function
          var B = () => {
              // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
              console.log(this); // global Object
          };
          
          B();
          
          // 초기화된 this 값을 반환한다.
          return this;
          
      }
          
      // this 는 global Object 로 초기화된다.
      A();
    
  • 생성자 함수 객체 내부에서의 Arrow Functionthis 값(Arrow Functionthis 값을 동적 바인딩하기위한 방법)

      function A(){
          
          // arrow function
          var B = () => {
              // 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(A Object) 값으로 초기화된다.
              console.log(this); // A Object
          };
          
          B();
          
          // 초기화된 this 값을 반환한다.
          return this;
          
      }
          
      // this 는 생성된 인스턴스로 초기화된다.
      console.log(new A()); // A Object
    
  • 객체 메서드에서의 this 는 해당 메서드를 둘러싼, 전역 스코프의 this 값으로 초기화된다.

      var A = {
          normalMethod: function(){
              return this; // A object
          },
          arrowMethod: () => {
              return this; // global object
          }
      };
          
      // 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다.
      console.log(A.normalMethod()); // A Object
          
      // 이 경우 this 는 (arrowMethod)함수를 둘러싼, 전역 스코프의 this(global Object) 값으로 초기화된다.
      console.log(A.arrowMethod()); // global Object
    
  • Arrow Function 내부에서의 this 값 변경

      var A = {
          arrowMethod: () => {
          
              var bindFn = function(){
                  console.log(this); // A object
              }.bind(A)();
          
              return this;
          }
      };
          
      console.log(A.arrowMethod()); // global Object
    
  • 그 밖의 테스트

          
      // 객체를 반환하기 위해서는 괄호 연산자 또는 return 문을 사용해야한다.
      {
          let a = () => {x: 1 };
          
          console.log(a()); // undefined
      }
          
      {
          let a = () => ({x: 1});
          
          console.log(a()); // {x: 1} object
      }
          
      {
          let a = () => { return {x: 1}; };
          
          console.log(a()); // {x: 1} object
      }
          
      // IIFE(즉시 실행 함수) 는 아래와 같이 표현될수 있다.
      console.log((() => 1)()); // 1
    

관련 URL

comments powered by Disqus