this에 대하여...

frenchkebab·2021년 9월 24일
0

javascript 지식

목록 보기
31/36
post-thumbnail

this에 대하여...

ZeroCho 블로그의 '자바스크립트의 this는 무엇인가?' 글을 참조하여 작성하였습니다.


this는 기본적으로 window 객체를 가리킨다

크롬의 콘솔창에서 this;를 입력하면 Window 객체를 가리키게 된다.

function a() {
  console.log(this);
};

a(); // Window 객체

기본적으로 Window 객체를 가리키는 것을 알 수 있다.


windows가 아닌 경우를 외우자

객체 '메서드' 안의 this는 해당 객체를 가리킨다.

let obj = {
  a: function() {
    console.log(this);
  }
};

obj.a(); // obj

객체 메서드 안의 this는 해당 객체를 가리킨다.
이는 객체의 메서드를 호출할 때 this내부적으로 바꾸어 주기 때문이다.


객체의 메서드인가? 그냥 함수인가?

하지만 다음과 같이 하면 결과가 달라진다.

let a2 = obj.a;
a2(); // window 객체

호출을 할 때 호출하는 함수객체의 메서드인지 그냥 함수인지가 중요하다.
a2obj.a를 꺼내온 것이기 때문에 더이상 obj의 메서드가 아니다.


함수 메서드 삼총사 bind, call, apply로 windows가 아닌 객체를 가리키도록

함수 메서드 삼총사 bind, call, apply 그리고 arguments 글을 참조하도록 하자.

명시적으로 this를 바꾸는 함수 메서드 삼총사 bind, call, apply를 사용하면 thisWindow 객체가 아닌 다른 객체를 가리키도록 할 수 있다.

let obj2 = { c: 'd' };
function b() {
  console.log(this);
}

b(); // Window
b.bind(obj2).call(); // obj2
b.call(obj2); // obj2
b.apply(obj2); // obj2

new를 붙여 생성자로 인스턴스를 생성하는 경우

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHi = function() {
  console.log(this.name, this.age);
}

생성자 함수도 함수이므로, new를 사용하지 않고 호출하면

Person('frenchkebab', 26);
console.log(window.name, window.age); // frenchkebab 26

this.namewindow.name,
this.agewindow.age가 되어버린다.

이를 막으려면 new 예약어를 사용해야 한다.

let hero = new Person('hero', 33); // Person {name: 'Hero', age: 33}
hero.sayHi(); // Hero 33

이렇게 new를 붙이면 this생성자를 통해 생성된 인스턴스가 된다.

이렇게 실수로 new를 붙이지 않는 문제를 막는 장치인 classES6에 추가되었다.


Event Listener 등을 사용하는 경우

document.body.onclick = function() {
  console.log(this); // <body>

얘는 그냥 함수인데 thiswindow가 아니라 <body>이다.

  • 객체 메서드도 아니고
  • bind한 것도 아니고
  • new를 붙인 것도 아니고

그럼 누가 바꾼걸까?
바로 이벤트가 발생할 때, 내부적으로 this가 바뀐 것이다.
내부적으로 바뀐 것이기 때문에 외우라고 한다...........

$('div').on('click', function() {
  console.log(this);
});

이러한 제이쿼리 코드의 경우 this클릭div가 된다.
내부적으로 function을 호출할 때 this를 그렇게 바꾸어 버린다.
이것도 어쩔 수 없이 외우라고 한다.....


inner 함수 - 미쳐버린 예시

$('div').on('click', function() {
  console.log(this); // <div>
  function inner() {
    console.log('inner', this); // inner Window
  }
  inner();
});

이 경우에는 미쳐버리게도 thiswindow 객체를 가리킨다.

함수의 this는 기본적으로 window라는 원칙을 충실히 따른 것이다.
click 이벤트 리스너가 내부적으로 this를 바꾸었음에도 명시적으로 알리지 않은 것이 문제이다.

이를 해결하기 위해서는,

$('div').on('click', function() {
  console.log(this); // <div>
  var that = this;
  function inner() {
    console.log('inner', that); // inner <div>
  }
  inner();
});

이렇게 변수에 this저장해 주어야 한다.

혹은 ES6 화살표 함수를 사용하면 가능하다.

$('div').on('click', function() {
  console.log(this); // <div>
  const inner = () => {
    console.log('inner', this); // inner <div>
  }
  inner();
});

ES6 화살표 함수thiswindow객체 대신 상위 함수this를 가져온다. (이 경우 <div>)


정리하자면...

this는 기본적으로 window이다. 하지만 아래의 경우 this가 바뀐다.

  • 객체 메서드
  • bind, call, apply
  • new

그리고 이벤트리스너 등도 this를 내부적으로 바꿀 수 있으니 this를 확인해 보아야 한다.

또한, 내가 선언한 functionthis는 항상 window라는 것을 잊지 말 것!

profile
Solidity에 대해 공부하고 있습니다.

0개의 댓글