JavaScript와 TypeScript의 This

캡틴 노드랭크·2021년 9월 8일
0

This는 정말로 제대로 공부하지 않으면 매우 헷갈리는 불편한 존재다..

JavaScript 의 This

핵심을 보자면,JavaScriptThis는 함수를 호출할때 어떻게 호출했는지에 따라 바뀐다.

당장 개발자 도구(F12)를 열어 This를 입력해보자

window이다.

TIP!

window 객체는 브라우저의 요소들과 자바스크립트 엔진, 모든 변수를 담는 객체이다.

함수로 만들어 함수 내부에서의 this는 다음과 같다.

이번엔 반대로 객체 내부 a라는 메소드에 this를 넣어보면 다음과같다.

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

obj.a();

결과는 obj라는 객체의 메소드 aobj를 가르킨다.

이번엔 obj.a를 꺼내서 b라는 변수에 할당하면, thiswindow를 출력한다.

let b = obj.a;

console.log(b) // window 어쩌구 저쩌구

그렇기 때문에, JavaScript에서 this는 함수로 호출했는지, 객체의 메서드로 호출했는지가 중요하다.

Lexical Scoping 는 함수를 선언할 때 결정된다. 함수의 상위 스코프를 결정하는 방식으로 가장 가까운 위치에서 상위 범위로 변수를 찾는 행위이다.
함수선언시 Lexical Scoping, 함수가 호출시 This binding

function a (x, y) {
     function b() {
       console.log(this);
     return x + y  
    
     }
  return b();
}

a(1,2) 

//window
//3

중첩 함수를 쓴다 하더라도 함수 b 내부의 thisWindow를 출력한다.

이게 골때리는게, 더 위의 obj 객체 예제에서 a라는 메소드의 내부함수를 추가로 작성하고 내부함수를 호출하면 내부함수의 this는 전역객체인 window를 바인딩한다.

단, 'use strict'가 작성된 Strict모드에서는 undefined.

Call, Bind, Apply 의 This

call,bind,apply 삼총사는 this를 명시적으로 가르키도록 해준다.

그래서 내부함수에서 this를 사용할 경우 가르키는 대상을 지정할 수 있다.

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

b() //whindow
b.bind(obj2)(); //obj2
b.call(obj2); // obj2
b.apply(obj2); //obj2
let value = 1;

let obj = {
  value: 100,
  foo: function() {
    function bar(a, b) {
      console.log(this);
      console.log("bar's arguments: ", arguments);
    }
    bar.apply(obj, [1, 2]);
    bar.call(obj, 1, 2);
    bar.bind(obj)(1, 2);
  }
};

obj.foo();

화살표 함수의 This

화살표 함수 () => {} 는 기본적으로this를 가지지 않는다. 그렇기 때문에 this를 사용하면 상위 스코프의 값을 가져온다. Lexical This라고 불리는 이유중 하나이다.

간단한 예를 보면

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

obj.a() //Window

일반 함수는 obj를 가르키겠지만 화살표는 보다 상위 스코프인 Window객체를 가르킨다.

function Prefixer(prefix) {
  this.prefix = prefix;
}

Prefixer.prototype.prefixArray = function (arr) {
  // this는 상위 스코프인 prefixArray 메소드 내의 this를 가리킨다.
  return arr.map(x => `${this.prefix}  ${x}`);
};

const pre = new Prefixer('Hi');
console.log(pre.prefixArray(['Lee', 'Kim']));

이 코드에서는this는 상위 스코프인 prefixArray를 가리킨다.
Prefixer {prefix: 'Hi'}

TypeScript는 명확하게 잡아낼 수 있다.

profile
다시 처음부터 천천히... 급할필요가 없다.

0개의 댓글