본문 바로가기
JavaScript

This에 대한 정리

by whoyoung90 2022. 1. 22.
반응형

다른 대부분의 객체지향 언어에서의 this는 클래스로 생성한 인스턴스 객체를 의미한다.

 

this가 결정되는 과정은 이런 흐름으로 결정된다.

함수 호출 => 실행 컨텍스트 생성 => EnvironmentRecord : 변수정보수집(호이스팅)
                                                                  OuterEnvironmentReference : 스코프체인
                                                                  ThisBinding : this가 결정

 

결국 함수를 호출할 때, this가 결정된다고 생각하면 된다

 

이러한 this가 상황에 따라 달라지는데 정리해보면 이렇다.

 

1.  메서드로서 호출

아주 간단하다. this는 프로퍼티명 앞의 객체

 

2.  함수로서 호출

호출 주체를 명시하지 않고 실행한 것이기 때문에 this가 지정되지 않는다.

결국, this가 지정되지 않은 경우 this는 전역 객체를 바라본다.

 

그렇다면 호출 주체가 없을 때 전역객체를 바인딩하지 않고

호출 당시 주변 환경의 this를 그대로 상속받게 하려면 어떠한 방법이 있을까?

 

2-1.  this를 우회하는 방법(ES5)

- var self = this와 같이 상위 스코프의 this를 저장해서 내부함수에서 활용

- call/applybind 메서드를 활용

let obj =  {
   outer: function() {
     console.log(this);        // obj { outer: ƒ outer() }

     let inner1 = function() {
       console.log(this);      // 전역객체 window
     }
     inner1();
        
     let self = this;
     let inner2 = function() {
       console.log(self);      // obj { outer: ƒ outer() }
     }
     inner2();
     
    let inner3 = function () {
      console.log(this);       // obj { outer: ƒ outer() }
    };
    inner3.call(this);
  
    let inner4 = function () {
      console.log(this);       // obj { outer: ƒ outer() }
    }.bind(this);
    inner4();

   }
};
obj.outer();

2-2. this를 바인딩하지 않는 함수(ES6)

함수 내부의 this가 전역객체를 바라보는 문제를 보완하고자 ES6에서 this를 바인딩하지 않는 화살표 함수가 도입!!

 

화살표 함수는 실행컨텍스트를 생성할 때 thisBinding 과정 자체가 빠지게 되어 상위 스코프의 this를 그대로 활용할 수 있다!!

(이 함수 내부에는 this가 아예 없으며, 접근하고자 하면 스코프체인상 가장 가까운 this에 접근)

Arrow Function => 실행 컨텍스트 생성 => EnvironmentRecord : 변수정보수집(호이스팅)
                                                                                  OuterEnvironmentReference : 스코프체인
                                                                                  ThisBinding : this가 결정    👉 상위 스코프의 this를 활용 가능!!!

 

3. 콜백 함수로서 호출

특별히 정의하지 않은 경우에는 전역객체 window

 

콜백 함수의 제어권을 가지는 함수가 콜백함수에서의 this를 결정.

👉 call/apply/bind로 특별히 정의
👉 thisArg(this로 지정할 객체)를 지정하면 콜백 함수 내부에서 this값을 원하는대로 변경할 수 있다!
/* bind로 특별히 정의 */
let obj = {
  testThis: function () {
    console.log(this);
  },
  testThisLater1: function() {
    setTimeout(this.testThis, 1000); // 특별히 정의하지 않은 경우
  },
  testThisLater2: function() {
    setTimeout(this.testThis.bind(this), 1500); // 콜백 함수의 제어권을 가지는 함수가 this를 결정.
  }
};
obj.testThisLater1(); // 전역객체 window
obj.testThisLater2(); // obj


/* 별도의 인자 thisArg 지정 */
Array.prototype.forEach(callback[, thisArg])
Array.prototype.map(callback[, thisArg])
Array.prototype.filter(callback[, thisArg])
// ... 등등

✅ 우리가 실무에서 map, forEach, filter등을 쓰면서 두번째 인자 ThisArg를 한번도 활용 안했던 이유?

👉 첫번째 인자 callback로 화살표 함수를 사용했기 때문!! 즉, ThisBinding을 신경 쓸 이유가 없었던 것이다🙂


4. 생성자 함수(new)로서 호출

this는 (전역객체가 아닌) "인스턴스 자신"

 

자바스크립트는 함수에 생성자로서의 역할을 함께 부여.

new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작한다.

 

생성자 함수로서 호출된 경우 내부의 this는 새로 만들어질 인스턴스 자신이 된다!

/* this는 전역객체가 아닌 인스턴스 자신 */
let Profile = function (name, age, work) {
  this.name = name;
  this.age = age;
  this.work = work;
}

let me = new Profile('김우영', '33세', '개발자');
let brother = new Profile('김동영', '29세', '회사원');

console.log(me); // Profile { name: '김우영', age: '33세', work: '개발자'} this가 인스턴스(me) 자신!
console.log(brother); // Profile { name: '김동영', age: '29세', work: '회사원'} this가 인스턴스(brother) 자신!

 

 

 

반응형

'JavaScript' 카테고리의 다른 글

forEach / for-in / for-of 차이점  (0) 2022.01.31
유사배열객체에 배열메서드 적용(call, apply)  (0) 2022.01.30
continue 문  (0) 2022.01.05
스코프 체인 예시  (0) 2021.12.25
JavaScript 안드로이드 아이폰 구분  (0) 2021.10.28

댓글