JavaScript

[javascript] this - 2

  • -

arrow 함수와 this

앞선 포스트에서 꾸역 꾸역 execution context와 this에 대해서 알아갈 무렵 ECMA6가 발표되면서 arrow 함수라는 것이 발표되고 또다시 this는 혼돈에 빠지게 된다.

https://goodteacher.tistory.com/438

 

[javascript] this -1

이번 포스트에서는 알쏭 달쏭 헤깔리는 javascript에서의 this에 대해서 살펴보자. javascript에서의 this javascript에서의 this가 어려운 이유는 그때 그때 달라지기 때문이다. 다른 언어에서의 this와 그

goodteacher.tistory.com

 

arrow 함수에서의 this

일반 함수에서 this실행환경 즉 execution context에 의해 좌우되는 반면 arrow 함수의 thislexical environment 즉 함수가 선언된 환경에 좌우된다. 말이 쓸데없이 복잡한데 정리하면 arrow 함수는 자체적으로 this를 바인딩하지 않고 외부의 this를 사용한다.

let cat = {
    name: "고리",
    eat: function () {
        console.log(`${this.name}이 밥을 먹는다.`, this);
    },
    sleep: () => {
        console.log(`${this.name}이 잔다.`, this);
    },
    info: function () {
        let getLen = () => {
            return this.name.length;
        };
        console.log(`${this.name}은 ${getLen()} 글자다.`);
    },
};

cat.eat();
cat.sleep();
cat.info();

위 코드에서 eat는 일반 함수이므로 execution context를 따르고 cat을 통해서 호출하므로 this는 cat이다.

다음으로 cat.sleep에 대해 살펴보자. sleep은 arrow 함수여서 외부(cat)의 lexical 환경을 가져오는데 cat은 전역에 선언된 객체이므로 cat의 lexical environment는 전역(window)이다. (객체 리터럴은 새로운 스코프를 만들지 않는다.)  따라서 cat.sleep에서 this는 window 객체이다.

마지막으로 info 내부에 있는 getLen을 살펴보자. 이 녀석도 arrow 함수이므로 외부의 this를 물려받는다. 여기서는 info라는 함수 내부에 있으므로 info의 this를 가져간다. info는 cat을 통해서 불려지므로 getLen의 this는 cat이 된다.

만약 아래와 같이 변경한다면?

let toGlobal = cat.info;
toGlobal();

이제 toGobal이 전역이고 toGlobal 내부의 getLen은 외부를 따라가므로 이때의 this는 전역 객체가 된다.

 

callback에서의 arrow 함수와 this

arrow 함수는 callback에서 사용할 때에도 조심해야 한다.

document.querySelector("#eat").addEventListener("click", cat.eat);
document.querySelector("#sleep").addEventListener("click", cat.sleep);
document.querySelector("#info").addEventListener("click", cat.info);

event handler 내부에서 this는 event source이다..  #eat 클릭 시 콜백의  this는 event source이다.

하지만 arrow 함수인 #sleep에서는 함수 선언시의 this가 바인딩 되므로 window이다.

마지막으로 #info의 경우는 외부 환경의 this를 바인딩 하므로 #eat와 같은 event source이다.

 

this 조심!!

정리하면 arrow 함수는 기존의 function을 간단히 작성할 수 있는 아주 좋은 표기법이지만 this 가 개입되면 머리가 복잡해지므로 조심해서 사용해야 한다. 

따라서 일반 함수건, arrow 함수건 함수 내에서 this를 사용할 계획이라면 사용되는 this가 누구인지 꼭 콘솔에서 확인하고 사용하자.

일반적으로 다음의 경우는 arrow 함수를 사용하지 않는 것이 정신 건강에 유리하다.

  • 객체의 함수 속성: 객체의 다른 속성을 가져가야 하는데 arrow 함수의 this는 객체를 가리키지 않으므로 불편하다.
  • 생성자 함수: arrow 함수는 생성자 함수로 사용할 수 없다.(에러 발생: arrow 함수에는 prototype이 없음)
  • 이벤트 헨들러: this는 이벤트 소스가 아닌 window를 가리키게 된다.
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.