[JS] 자바스크립트에서 This

GyungHo Go·2021년 3월 20일
2

개인적으로 자바스크립트에서 this의 정확한 의미를 알기 어려웠다. 특히 다른 프로그래밍 언어에서의 this와 다른 성격을 갖고있기 때문에 더 어렵게 느껴지는 것도 있을 것이다.

다른 객체지향 프로그래밍 언어에서 this란 클래스 자신을 가리키는 것을 말한다.

class Car {
 engine: number;
 
 move() {
  this.engine++;
  }
}

여기서 this란 만들어진 객체 자기 자신을 의미한다.
반대로 자바스크립에서 this는 누가 호출하느나에 따라서 this가 달라질 수 있다.

자바스크립트에서 this라는 것은 지금 호출한 사람의 문맥을 타나내는 것이다. 그래서 아무것도 하지 않고 콘솔창에 this를 그냥 쳐보면 window라는걸 알수있다. 이유는 브라우저 환경에서는 window가 글로벌 객체이기 때문이다.

이번엔 this를 함수 안에 넣어서 출력해보면 그래도 window라는걸 알수 있다.
글로벌에서 함수를 호출하는 것은 window에 있는 것을 호출하는 것과 동일하다.

class Counter {
	counter = 0;
    increase = function () {
    console.log(this);
    }
 }
 const counter = new Counter();
 counter.increase();


여기서 this는 Counter가 된다.

class Counter {
	counter = 0;
    increase = function () {
    console.log(this);
    }
}
const counter = new Counter();
counter.increase();
const func = counter.increase; //func이라는 변수에 새롭게 할당
func(); //undefined

counter에 increase 함수를 func에 새롭게 할당해보자.
func(); 를 호출해 보면 콘솔창엔 undefined가 나오는걸 알 수 있다.
원래 counter에 increase 에 있는 thisCounter 클래스를 가리키고 있었다.
하지만 increase를 func이라는 변수에 할당 했기 때문에 this의 정보를 잃어 버리게 된다. 이유는 let과 const로 선언한 변수는 window에 등록되어있지 않기 때문에 func을 호출하는 것은 window가 아니라 어떤 object도 아니기 때문에 여기서 this는 undefined가 나오게 된다.

class Counter {
	counter = 0;
    increase = function () {
    console.log(this);
    }
}
const counter = new Counter();
counter.increase();
const func = counter.increase; 
func();

class Bob {}
const bob = new Bob();
bob.run = counter.increase;

새롭게 Bob 클래스를 만들고, bob에 run 이라는 함수에 counter.increase를 할당해 준다.

그러면 Bob자체가 출력되는것을 볼 수 있다.

자바스크립트에서 this라는 정보를 다른곳에 할당하는 순간 잃어 버릴수 있기 때문에 우리가 object와 함수의 관계를 묶어줄 필요가 있다. 이를 bind라고 한다.

class Counter {
	counter = 0;
    increase = function () {
    console.log(this);
    }
}
const counter = new Counter();
counter.increase();
//const func = counter.increase; 
const func = counter.increase.bind(counter); // counter object와 바인딩

자바스크립트에서 this란 호출하는 함수에 따라서 변경될 수 있기 때문에 한 곳으로 object와 연결하고 싶으면 bind라는 함수를 이용해서 연결해주어야 한다.

여기서 bind을 일일이 해주지 않아도 되는 방법이 있다.

class Counter {
	counter = 0;
    increase = () => {  //arrow function을 사용
    console.log(this);
    }
}
const counter = new Counter();
counter.increase();
const func = counter.increase; 
//const func = counter.increase.bind(counter); counter object와 바인딩

클래스 안에서 함수를 선언할때, arrow function을 사용하면 따로 바인딩 하지 않아도 된다.
arrow function을 사용하게 되면 선언 당시의 scope의 this를 유지하게 된다.

참고

https://academy.dream-coding.com/collections

profile
기록하는 습관

0개의 댓글