Javascript | this | 화살표

var obj = {
    name: "B",
    print: function () {
      var inner1 = function () {
        console.log(this.name, name);
      };
      inner1();

      var inner2 = () => {
        console.log(this.name, name);
      };
      inner2();

      var name = "C";
      console.log(window.name, this.name, name);
    },
  };

  name = "A";
  obj.print();

내가 햇갈리는 것

  1. print() 안에서 name이 가지는 값을 잘 모르겠다. 오류가 나야할것 같은데?
    => 지난 호이스팅 관련 글에 정리하였습니다.

  2. this가 무엇을 의미해서 this.name이 달라지는지 모르겠다.
    => 이번 포스팅에 정리합니다.

this

this는 함수 호출에 따라 달라지는 자기 자신 참조 객체입니다.
일반적으로는 전역 객체 (브라우저에서는 window, node 환경에서는 global)를 뜻합니다.
메소드나 생성자 함수에서 this는 자기 자신을 뜻합니다.

말이 좀 어려워서 코드를 통해 알아봅시다.

  var obj = {
    name: "B",
    print: function () {
      console.log("obj.print 안의 this");
      console.log(this);
      var inner1 = function () {
        console.log("obj.print 안의 inner1 안의 this");
        console.log(this);
        console.log(this.name, name);
      };
      inner1();

      var inner2 = () => {
        console.log("obj.print 안의 inner2 안의 this");
        console.log(this);
        console.log(this.name, name);
      };
      inner2();

      var name = "C";
      console.log(window.name, this.name, name);
    },
  };

  name = "A";
  console.log("기본 this");
  console.log(this);
  obj.print();

위 코드는 각 구간마다 this가 어떻게 달라지는지 알아보기 위해 하나하나 로그를 남깁니다.

기본적으로 this는 전역 객체에 해당하기 때문에 window를 뜻합니다.

obj.print()가 선언되었을 때 print() 안에서 this는 obj의 메소드가 호출된 것이므로 자기 자신 obj가 this가 됩니다.

print() 안의 inner1 안에서 this는 다시 전역 객체 window를 뜻합니다.
print() 안의 this만 메소드로서의 영향을 받습니다. inner1에는 영향을 주지 않습니다.

print() 안의 inner2 안에서는 왜 this가 전역 객체가 아닐까요?
inner2가 화살표 함수이기 때문입니다.

화살표 함수

화살표 함수의 배경

[10, 20, 30].map(function (element) {
  return element * 2;
})
// [20, 40, 60]

화살표 함수 이전에는 function 키워드로 함수를 사용했습니다.

function() {
  // logic
}

그러나 function 키워드는 함수를 간단하게 표기할 수 없었고, 좀 더 간략하게 사용할 수 있는 화살표 함수가 등장했습니다.

화살표 함수의 특징

  1. 화살표 함수는 익명함수로만 사용할 수 있습니다.
function () {
  // logic
}

() => {
  // logic
}

위 두 코드는 같은 코드입니다. 화살표를 통해 function 키워드 없이 간단하게 사용할 수 있습니다.
익명함수로만 사용할 수 있으므로 함수 선언식이 아닌 함수 표현식을 사용합니다.

특히 콜백함수로 사용할 때 간결함이 드러납니다.

[10, 20, 30].map((element) => { return element * 2 })
// [20, 40, 60]

// parameter 괄호 생략, return 생략
[10, 20, 30].map(element => element * 2)
// [20, 40, 60]

['1', '2', '3'].map(Number)
// [1, 2, 3] 모두 string이 아닌 number

parameter가 1개일 경우 괄호를 생략할 수 있습니다.
특정 로직없이 return만 있는 경우 return 생략이 가능합니다.

2. this가 다르다.

화살표 함수의 this는 정적으로 언제나 화살표 함수를 선언한 부분의 this와 같습니다.
print()안의 inner2가 화살표 함수이기 때문에 inner2에서의 this는 print()의 this인 obj와 같습니다.

결론

this가 무엇을 의미하는지를 이해했습니다.
this.name이 무엇을 의미하는지 이해했습니다.

print()는 obj 객체의 메소드이므로 this가 obj를 뜻합니다.

print()안의 inner1는 function 함수이므로 this가 전역객체를 뜻합니다.
따라서 inner1안의 this.name은 window.name으로 'A'를 뜻하고, name은 print()에서 호이스팅되어 선언만 되고, 초기화가 안되어 undefined이다.

print()안의 inner2는 화살표 함수이므로 this가 print()의 this인 obj와 같습니다.
따라서 inner2안의 this.name은 obj.name으로 'B'를 뜻하고 name은 마찬가지로 undefined입니다.

print()안의 this.name은 obj.name이므로 'B'를 뜻하고, name은 'C'입니다.

정리

일반적으로 this는 전역 객체를 뜻하지만, 호출 방법에 따라 바뀝니다.
화살표 함수 this는 정적으로 선언한 곳의 this와 같습니다.

참고

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
https://poiemaweb.com/js-this
https://poiemaweb.com/es6-arrow-function

좋은 웹페이지 즐겨찾기