JavaScript Transcompile 을 진행해보자

예전 진행한 프로젝트에서 function 을 arrow function 으로 변환하는 도중 다음과 같은코드가 있었다.

let someThingObject = {
  something : 'test' ,
  getSomthing : function () {
    return this.somthing;
  }
}

someThingObject.getSomthing(); //test

해당코드를 다음과 같이 변환하고있는데 일반 function 에서는 잘되던 this 값이 arrow function 으로 이동되면서는 전달되지 않는 문제가 생겼다. arrow function 은 this 를 that 이나 bind 함수 없이 쓸수있도록 도와준다고 알고있었는데 적용이 안되어서 테스트를 진행해 보았다.

let someThingObject = {
  something : 'test' ,
  getSomthing : () => {
    return this.somthing;
  }
}
someThingObject.getSomthing(); //undefined

node 랑 npm 은 설치 되어있다고 가정하고 진행한다.

setUp

npm install babel-cli -g

/usr/bin/babel-doctor -> /usr/lib/node_modules/babel-cli/bin/babel-doctor.js
/usr/bin/babel -> /usr/lib/node_modules/babel-cli/bin/babel.js
/usr/bin/babel-node -> /usr/lib/node_modules/babel-cli/bin/babel-node.js
/usr/bin/babel-external-helpers -> /usr/lib/node_modules/babel-cli/bin/babel-external-helpers.js

cd /home
mkdir ./babeltest
cd ./babeltes

//babel preset setup
npm install --save-dev babel-preset-es2015t

//babelrc
vim ./.babelrc
{
  "presets":["es2015"]
}

기초세팅종료.

test.js

vim ./test.js

let testObj = {
  testVal : '1234',
  callArrow : () => {
    console.log(this.testVal)
  },
  callFunction : function () {
    console.log(this.testVal);
  },
  callFunctionInArrow : function() {
    setTimeout(() => {
        console.log(this.testVal);
    });
  },
  callFunctionInFunction : function() {
    setTimeout(function () {
      console.log(this.testVal);
    });
  },
  callArrowInArrow : () => {
    setTimeout(() => {
        console.log(this.testVal);
    });
  },
  callArrowInFunction : () => {
    setTimeout(function() {
        console.log(this.testVal);
    });
  },
}
testObj.callArrow(); //undefined
testObj.callFunction(); //1234
testObj.callFunctionInArrow(); //1234
testObj.callFunctionInFunction(); //undefined
testObj.callArrowInArrow(); //undefined
testObj.callArrowInFunction(); //undefined

babel compile

babel ./test.js -o ./test_compile.js

vim ./test_compile.js

'use strict';

var testObj = {
  testVal: '1234',
  callArrow: function callArrow() {
    console.log(undefined.testVal);
  },
  callFunction: function callFunction() {
    console.log(this.testVal);
  },
  callFunctionInArrow: function callFunctionInArrow() {
    var _this = this;

    setTimeout(function () {
      console.log(_this.testVal);
    });
  },
  callFunctionInFunction: function callFunctionInFunction() {
    setTimeout(function () {
      console.log(this.testVal);
    });
  },
  callArrowInArrow: function callArrowInArrow() {
    setTimeout(function () {
      console.log(undefined.testVal);
    });
  },
  callArrowInFunction: function callArrowInFunction() {
    setTimeout(function () {
      console.log(this.testVal);
    });
  }
};
testObj.callArrow(); //undefined
testObj.callFunction(); //1234
testObj.callFunctionInArrow(); //1234
testObj.callFunctionInFunction(); //undefined
testObj.callArrowInArrow(); //undefined
testObj.callArrowInFunction(); //undefined

위와 같이 애초에 this 값이 undefined 로 변환되서 저장되는것을 확인할수있다.

화살표 함수에서 this 를 찾을수 없는 이유는

화살표 함수는 자기 자신의 this 를 가지고있지않는다.(bind 와 같은 행위를 할수없음) 따라서
화살표 함수 내에서 this 에 대한 호출이 일어나면 this에 대한 바인딩을 찾기위해 화살표 함수의 범위를 찾기 시작한다.
일반 함수 (function a () {}) 와 global scope 만이 this 를 소유할수 있기때문에 화살표 함수는 object 안에서의 this 를 찾을수 없다. 따라서 최상위 (global scope) 의 this 를 참조하게 된다.

참조