Home This
Post
Cancel

This

개요


자바스크립트를 사용하면서 정확히는 모르지만 예측하며 사용했던 this에 대해 호기심이 생겨 공부하고 싶었다. 자바스크립트에서 This는 다른 언어의 this와는 다르다. 다른 특성 때문에 내가 정확히 사용을 못하지만, 예측은 가능하게 됐다고 생각한다. (참으로 아이러니 하다..)😅
이번 글을 통해 this를 이해할 수 있는 글을 써 보는 것이 목표이다.

This?


자바스크립트에서 This란 함수 호출 시 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정되는 것을 말한다.

전역 실행 컨텍스트에서 This

this는 엄격모드 여부에 관계 없이 전역 개체를 나타낸다. 일반적으로 this를 호출 하면 안되고 아래와 같이 함수에서 리턴을 해야 둘다 올바르게 나온다.

1
2
3
4
5
6
7
function f1() {
  return this;
}
// 브라우저
console.log(f1() === window); //true
// node.js
console.log(f1() === global); //true

객체의 메서드 This

1
2
3
4
5
6
7
8
const people = {
  age: 27,
  printAge: function () {
    return this.age;
  },
};

people.printAge(); //27

함수를 어떤 객체의 메서드로 호출하면 this의 값은 그 객체를 사용한다.

생성자 This

1
2
3
4
5
6
7
function dog(name, age) {
  this.name = name;
  this.age = age;
}

console.log(dog("gomi", 3)); //Uncaught TypeError: Cannot set property 'name' of undefined
console.log(new dog("gomi", 3)); //dog {name: "gomi", age: 3}

함수에서 this를 반환하고 싶다면 new 키워드를 사용하면 this는 함수에 묶인다.

DOM 이벤트에서 This

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
<body>
  <button type="button" id="this-btn">this</button>
  <script>
    const thisBtn = document.querySelector("#this-btn");
    thisBtn.addEventListener("click", function (event) {
      // 모두 출력결과 <button type="button" id="test-btn">test</button>
      console.log(this);
      console.log(event.currentTarget);
      console.log(event.target);
    });
  </script>
</body>
...

this는 DOM에서도 접근이 가능하다.

에러를 통해 This를 설정하는 방법


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function FrontTeam(members) {
  this.members = members;
  this.perform = function () {
    //참고로 여기서 this를 찍으면 FrontTeam을 가리킨다.
    setTimeout(function () {
      this.members.forEach(function (member) {
        //여기서 에러!!
        member.perform();
      });
    }, 1000);
  };
}

const developer = new FrontTeam([
  {
    name: "seonjae",
    perform: function () {
      console.log("HTML CSS JS REACT");
    },
  },
]);

developer.perform();

에러가 나는 이유는 this는 window(전역)을 가리키고 있고 window.members가 undefined이기 때문에 에러가 난다. 그래서 우리는 setTimeout의 callback함수에서 this를 FrontTeam을 가리키게 해야 된다. 그러기 위해서는 3가지 방법이 있다.

1. 화살표 함수

1
2
3
4
5
6
setTimeout(() => {
  //화살표 함수를 사용
  this.members.forEach(function (member) {
    member.perform();
  });
}, 1000);

화살표 함수는 자신의 function scope를 생성하지 않고 자기가 속해있는 scope를 찾아 this를 반환하기 때문에 여기서 this는 FrontTeam를 가리켜서 에러를 해결할 수 있다.

2. bind 메서드

1
2
3
4
5
6
7
8
setTimeout(
  function () {
    this.members.forEach(function (member) {
      member.perform();
    });
  }.bind(this),
  1000
);

bind 메서드를 통해 함수를 bind의 첫 번째 파라미터로 this 값을 영구적으로 고정한다. 만약 this 값을 바꾸고 싶어서 다시 bind를 사용한다면 한 번만 동작하기에 반영이 되지 않는다.

3. closure

1
2
3
4
5
6
7
8
9
10
11
function FrontTeam(members) {
  const that = this; //closure
  this.members = members;
  this.perform = function () {
    setTimeout(function () {
      that.members.forEach(function (member) {
        member.perform();
      });
    }, 1000);
  };
}

this.perform의 함수가 외부의 that(FrontTeam을 가르키는 this)을 참조하는 것을 closure라고 한다. closure를 사용하면 에러를 해결할 수 있다.


https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
https://github.com/FEDevelopers/tech.description/wiki/자바스크립트에서-사용되는-this에-대한-설명-1#1-this에-대한-미스터리
https://blueshw.github.io/2018/03/12/this/
https://kyu9341.github.io/JavaScript/2020/12/24/JavaScript_this/

-- Missing configuration options! --