[ES6] 화살표 함수와 this, 실행문맥(Execution Context)

권준혁·2020년 11월 1일
0

javascript

목록 보기
12/19
post-thumbnail

안녕하세요 !

지난시간에 실행컨텍스트 (이하 실행문맥)에 대해서 정리해봤습니다.

ES6이후에는 실행문맥의 LexicalEnvironment에 this바인딩도 함께 있다는 걸 봤었는데요

함수가 호출되어 함수문맥이 생성될 때 object reference로 호출됐는지에따라 this가 가리키는 것이 바뀔 수도 있습니다.

그리고, 함수의 선언방법에 따라서도 this가 달라질 수도 있습니다.
함수의 선언에는 표현식, 선언식이 있습니다. (생성자를 이용한 방법 제외) 화살표 함수는 좀 다릅니다.


  • this값이 달라지는 경우
  • object reference에 따라
  • 함수 선언방법에 따라

object reference로 호출됐을 경우

const obj = {
    message : '안녕하세요?',
    setMessage (name) {
        return `${name}${this.message}`
    }
}
console.log(obj.setMessage('jack'))
// result
jack님 안녕하세요?

이 코드에서 this가 가리키는 것은 obj입니다.
obj.setMessage('jack)으로 호출했을 때, 함수 컨텍스트가 생성되면서
this값에 obj가 바인딩됩니다.

전역객체에서 호출됐을 경우

const print = obj.setMessage
console.log(print('jack'))
// result
jack님 undefined

이 코드에서는 obj.setMessage를 새로운 변수에 할당했습니다.
그리고 print('jack')으로 호출 했을 때, 함수 컨텍스트가 생성되면서
this값에는 기본으로 갖는 전역객체가 바인딩됩니다.
결과적으로 this.message는 undefined가 반환됩니다.


  • this값이 달라지는 경우
  • object reference에 따라
  • 함수 선언방법에 따라

콜백함수를 선언식으로 작성한 경우와 화살표함수로 작성한 경우

const greeting = {
    setMessages (...names) {
        return names.map(function (item) {
            return `${item}${this.message}`
        })
    },
    setMessagesArrow (...names) {
        return names.map((item) => {
            return `${item}${this.message}`
        })
    }
}
console.log(greeting.setMessages(...names))
console.log(greeting.setMessagesArrow(...names))

두 함수를 각각 실행한 결과는 어떻게 될까요?

// result
[ 'jack님 undefined', 'kong님 undefined', 'hyuk님 undefined' ]
[ 'jack님 어서오세요', 'kong님 어서오세요', 'hyuk님 어서오세요' ]
  • 함수를 선언식으로 작성한 경우 함수컨텍스트가 생성되어 this바인딩을 새로만듭니다. this바인딩이 greeting객체가 아니라 전역객체가 되어 undefined가 반환됩니다.
  • 함수를 화살표함수로 작성하게되면 this바인딩을 새로 만들지 않습니다. 결과적으로 의도된 대로 작동하게 됩니다.

무조건 화살표함수를 써야할까요?

const greeting = {
    message : '어서오세요',
    setMessage (name) {
        return `${name}${this.message}`
    },
    setMessageArrow : (name)=> {
        return `${name}${this.message}`
    }
 }
 console.log(greeting.setMessage('jack'))
console.log(greeting.setMessageArrow('jack'))

// result
jack님 어서오세요
jack님 undefined

바로 이전의 코드와 다른점은 인수가 배열이 아니기때문에 map()메서드를 사용하지 않고 인수와 함께 this.message를 문자열로 리턴됩니다.

명명된 함수와 다르게 화살표함수는
greeting.setMessageArrow('jack')를 실행하더라도 this바인딩이 없기 때문에 undefined가 됩니다.


이런 문제는 React에서 클래스형 컴포넌트를 작성하다보면 많이 마주치게됩니다. 저도 "무조건 bind(this)로 this바인드를 연결하거나, 화살표함수를 써야한다" 라고 외웠는데 JS엔진에서 컨텍스트의 this바인딩 문제였습니다.

다음포스팅은 자바스크립트에서의 Class와 거기에서 발생하는 문맥문제도 살펴보습니다.

profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글