치춘짱베리굿나이스

this in JavaScript 본문

Javascript + Typescript/이론과 문법

this in JavaScript

치춘 2023. 7. 26. 21:36

this

매우 매우 헷갈리는 그 this이다

전역 스코프에서의 this

브라우저

console.log(this);

브라우저에서의 전역 스코프에서 thisWindow 객체를 가리킨다

Node.js

node.js 환경에서의 this는 현재 module.exports 객체를 가리킨다고 한다

브라우저처럼 Global 객체를 가리킬 것 같지만 아니다

 

const a = 2; // 영향 X
module.exports.a = 3;
console.log(this);

따라서 해당 객체에 값을 넣으려면 module.exports 를 해 주어야 한다

 

console.log(globalThis);

globalThisglobal 객체를 가리킨다

함수 호출 시의 this

단순 호출

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

foo()

단순 호출 시에는 호출된 시점에서의 부모 객체를 참조하므로, 위에서 foo가 호출되었을 때의 부모 객체인 Window (또는 global) 객체가 출력된다

객체 내부에서의 호출

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

const class1 = {
  value: 1,
  func: foo,
};

class1.func();

객체 내부에서 객체의 메서드로서 호출이 될 경우 해당 객체가 출력된다

객체 내부에 있는 함수를 외부로 빼내어 호출

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

const class1 = {
  value: 1,
  func: foo,
};

const func = class1.func;
func();

이 경우 함수 func는 전역에서 호출되었으므로 전역 객체가 출력된다

생성자

function foo() {
  this.value = 2;
}

const obj = new foo();
console.log(obj.value);

함수를 생성자로 사용할 경우, this는 새로 생성되는 객체를 가리킨다

call, apply, bind

call

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

const class1 = {
  value: 1,
  func: foo,
};

const class2 = {
  value: 2,
};

class1.func.call(class2);

call을 이용하면 this를 재할당한 뒤 함수를 호출할 수 있다

여기서 functhisclass2로 바꿔준 뒤 호출했으므로 value는 2가 된다

 

function foo(n) {
  console.log(this);
    console.log(n);
}

const class1 = {
  value: 1,
  func: foo,
};

const class2 = {
  value: 2,
};

class1.func.call(class2, 2);

call은 두 번째 인자부터 “실행시킬 함수의 인자”를 받는다

여기서 두 번째 인자에 2를 넘겼기 때문에 foo(n)n2가 들어갔음을 확인할 수 있다

apply

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

const class1 = {
  value: 1,
  func: foo,
};

const class2 = {
  value: 2,
};

class1.func.apply(class2);

call 메서드와 완전히 동일한 동작을 한다

부모 객체가 바뀌어 class2가 출력되는 것을 볼 수 있다

 

function foo(n) {
  console.log(this);
    console.log(n);
}

const class1 = {
  value: 1,
  func: foo,
};

const class2 = {
  value: 2,
};

class1.func.apply(class2, [2]);

applycall과 다르게 “실행시킬 함수의 인자” 를 배열로 받는다는 차이가 있다

bind

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

const class1 = {
  value: 1,
  func: foo,
};

const class2 = {
  value: 2,
};

const bar = class1.func.bind(class2);
bar();

bind는 부모 객체 (this) 를 영구적으로 바꾼 값을 반환한다

bar 함수는 func의 부모 (this) 를 class2로 바꾸어준 결과물이다

화살표 함수

호출

const func = () => {
  console.log(this);
};

const class1 = {
  value: 1,
  func: () => {
    console.log(this);
  },
};

func();
class1.func();

화살표 함수는 this가 없기 때문에 상위 스코프에서 this를 찾는다

따라서 위의 경우에는 전역 스코프를 가리키게 된다

 

const class1 = {
  value: 2,
  func: function () {
    const foo = () => {
      console.log(this);
    };
    foo();
  },
};

class1.func();

이렇게 하면 func 함수의 스코프에서 this가 존재하므로, 해당 this를 가져와 출력한다

bind, call, apply

const class1 = {
  value: 1,
  func: () => {
    console.log(this);
  },
};

const class2 = {
  value: 2,
};

class1.func.call(class2);
class1.func.apply(class2);
const bar = class1.func.bind(class2);
bar();

화살표 함수는 bind, call, apply를 무시한다는 것을 기억하자

화살표 함수의 this는 함수 생성 시점의 것으로 고정된다


참고 자료

https://www.reddit.com/r/node/comments/cjbn9x/why_this_is_empty_in_global_scope_in_nodejs/

https://stackoverflow.com/questions/43627622/what-is-the-global-object-in-nodejs

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

Comments