JS - two hours daily : this

박상하·2023년 9월 4일
0

TIL  CS/JS

목록 보기
16/22

오늘은 this에 대해 학습을 했다.
평소에 this가 많이 헷갈렸기 때문에 공부를 하기에 망설여졌었다. 하지만 언젠가는 해야한다면 오늘 그냥 해버리자! 마음 먹고 this에 대해 접근해보았다.

this는 언제 결정되지 ❓

this는 무엇일까, this는 실행컨텍스트가 형성될 때 this가 형성이 된다. 필자가 보통 개발을 할때 this를 사용한 기억을 먼저 생각해봤다. class를 만들어 객체지향개발을 할 때 this를 많이 사용했었다. this는 class를 가르키고 후에 생성이 되면 새로 생성된 인스턴스를 가르켜 이를 통해 메서드를 호출하거나 class 내부의 필드값을 this로 가져와 객체 내부적으로 동작하게 한 경험이 있었다.

대략적으론 알고있지만 마구 겹쳐져있는 함수에서 this가 가르키는 걸 찾으라고하면 자신있게 대답할 수 없을 거 같았다. this는 도대체 누구일까?

this는 결국 호출하는 방법에 의해 결정된다.
this는 공부해보니 아주 바람과 같은 친구이다. 누가 호출하고 어떻게 호출하느냐에 따라 동적으로 this의 값이 바인딩 된다.

이게 핵심이다. 결국 this는 누가 나를 호출했느냐에 따라 결정되고 대체적으로 나를 호출한 놈이 된다.

코드로 살펴보는 this ❗️

다음과 같은 코드가 있다.

function Test(){
 console.log(this)
  
}

Test()

결과는 ? window 객체를 가르킨다.
일단 this를 사용하는 함수는 Test인데 이를 어떻게 호출했는지보자

"호출 방식에 따라 this의 값은 결정된다."

Test는 그냥 Test로 호출한 거 처럼 보이지만 사실은 window.Test()와 동일하다.
결국 Test를 window가 호출한 것이고 this는 window로 동적 바인딩이 된다.


두 번째 예제이다.

const obj={
 name:"상하",
 getName:function(){
  console.log(this.name) 
 },
 getThis:this
}
obj.getName()
console.log(obj.getThis)

다음의 결과는 어떻게 나올까?

먼저 getName은 함수로 this.name을 호출한다. getName안에서의 this는 누구를 가르킬까? 일단 getName은 obj.~~에 의해 호출된다.

obj.getName 그렇기 때문에 this는 obj를 가르킨다.

그럼 getThis의 결과는 어떻게 나올까? getThis는 일단 함수가 아니기 때문에 호출 될 때 결정되는 것이 아니다. 결국 그냥 선언 될 때 결정이 된다. 그렇기 때문에 this는 obj가 아닌 window가 설정된다!

아직은 헷갈린다 더 예제를 추가해보겠다.


세번째 예제

const Obj ={
 name:"상하",
 getName:function(){
  console.log(this.name)
function what(){
 console.log(this) 
}
  what()
 const what2 =()=>{
  console.log(this.name) 
 }
 what2()
 },
what3:function(){
 console.log(this) 
}
}

Obj.getName()
Obj.what3()

자 먼저 getName함수는 Obj의 내부에 선언되었고 getName을 호출하는 놈이 Obj.getName이기 떄문에 this는 getName으로 binding 된다.

그리고 what은 getName 내부에 선언되었지만 함수를 호출할 땐 what()으로 단독으로 실행되기 때문에 this에 window 객체가 바인딩된다.

what3는 getName과 동일하게 Obj내부에 선언되어 this를 가르키기 때문에 함수를 사용할 때 Obj.what3로 호출되니까 this는 Obj로 바인딩된다.


const Obj1={
  car:"현대",
getCar:function(){
 console.log(this.car) 
}
}

const Obj2={
 car:"기아",
  getCar:Obj1.getCar
}

Obj2.getCar()

이건 무엇이 나올까?? 바로 기아가 나온다.

Obj1.getCar는 this.car를 출력하는 함수이다. Obj2에서 호출을 하다보니 this가 Obj2가 된것이다.

그냥 Obj1.getCar() 를 실행했다면 "현대"가 출력 될 것이다.

이렇게 this는 누가 호출하냐에 따라 다르게 바인딩 된다.


일반함수에서는 어떨까

function What(){
 const B = console.log(this)
 const C ={
  D:"상하",
  F: this
 }
 console.log(C.F)
}
What()

이렇게하면?? 확실한건 그냥 함수가 아닌 변수로 this를 지정한다면 해당 this는 그 시점에서 바로 this가 바인딩된다. 즉 const C를 보면 C는 사실 그냥 C로 사용이 가능하다 호출을 할때 C 이렇게 사용되기 때문에 this는 window를 가르킨다.


function A(){
 function B(){
  console.log(this) 
 }
  B()
}
A()

이렇듯 this는 어디에 선언되느냐보단 어떻게 호출되느냐에 따라 정해지고

주의할 점은 this가 그냥 바로 할당되는경우는 보통 window객체를 가르킬것이다. 왜냐하면 거의 호출이 바로 사용되기 때문.

const bb= {
 name:"상하",
  getName:function(){
   console.log(this.name)
    const inner={
     test:this
    }
    console.log(inner.test)
  }
}
bb.getName()

여기에서도 볼 수 있다. inner는 getName 함수 내부에 있는 객체이지만 test는 바로 this를 저장한다. 그럼 inner 입장에서 this는 무엇일까를 고민하면된다. inner입장에서 this는 getName이 된다.

const bb= {
 name:"상하",
  getName:function(){
   console.log(this.name)
  function Inner(){
   console.log(this) 
  }
    Inner()
  }
}
bb.getName()

그럼 여기에서 Inner의 this는 또 window 객체를 가르킨다.

chat gpt this 정리 ❓

그럼 실행컨텍스트가 형성될 때 this가 바인딩 ❓

실행 컨텍스트가 형성될 때 this가 바인딩된다고 학습했었다 ! 그런데 갑자기 동적으로 함수를 누가 어떻게 호출하느냐에 따라 다르게 바인딩 된다니? 이게 무슨말이지??

그러니까 결론은

실행컨텍스트가 형성될 때 Javascript 해석기는 코드를 읽고 this를 동적으로 바인딩해준다. 이때의 기준이 누가 어떻게 호출하느냐에 따라 정해진다.

이렇게 정해지는 기준은 다음 5가지의 경우가 있다.

  1. 일반함수에서의 호출
    일반 함수가 this를 호출하게 되면 해당 this는 window 객체를 가르킨다.
    이도 그럴 수 밖에 없는게 결국 일반함수도 window.~~로 호출되는 것이기 때문에 결국 호출하는놈은 window이다.
  2. 메서드 호출
    메서드 호출이란 객체방식으로 함수를 호출하는것을 말한다.
    이때 this는 메서드를 호출한 객체가 된다.
const obj={
 name:"sangha",
getThis:function(){
console.log(this.name)
}
}
obj.getThis()
//sangha
  1. 생성자함수 호출
    생성자 함수 호출이란 생성자 함수나 class를 이용해 인스턴스를 만들 때 this는 새로 생성된 객체 즉, 인스턴스가 된다.
  2. 화살표 함수에서의 호출
    화살표함수에서는 상위 scope의 this를 그대로 따라가게된다.
  3. 이벤트 핸들러에서의 호출
    이벤트 핸들러에서 this를 호출하게 되면 이벤트가 발생한 DOM요소를 가르키게 된다.

크게 위 5가지 기준에 따라 실행컨텍스트가 형성될때 this는 바인딩된다.

profile
프론트엔드 엔지니어 꿈나무

0개의 댓글