3 minute read

this란?

JavaScript에서 thisobject(객체)에 대한 참조이다. this 가 어떻게 사용되거나 호출되었는지에 따라 어떤 객체를 참조할지 결정된다. 이번 글에서 this의 여러 면모를 살펴보자.

  1. 객체의 메소드 안에서, this해당 객체를 참조한다.
  2. 홀로 사용된 thisglobal object(전역 객체)를 참조한다.
  3. 함수 내부에서 thisglobal object(전역 객체)를 참조한다. (단, strict mode에서는 undefined)
    1. 고차함수의 콜백함수 안에서 thisglobal object(전역 객체)를 참조한다.
    2. 화살표 함수 안에서 this는 언제나 상위 스코프의 this를 가리킨다.
  4. 이벤트 내부에서 this 는 이벤트를 받은 해당 element를 참조한다.
  5. call(), apply(), bind()와 같은 메소드는 this어떤 객체로도 참조시킬수 있다.
  6. 체이닝

this는 변수가 아닌 keyword이다. this 의 값을 변경할수는 없다.

객체의 메소드 내부

const person = {
  firstName: "John",
  lastName: "Doe",
  id: 5566,
  fullName: function () {
    return this.firstName + " " + this.lastName;
  },
};

객체의 메소드 내부에서, this는 해당 객체를 참조한다. 위의 예시에서 person 객체의 메소드인 fullName에서 사용된 thisperson 객체를 참조한다.

홀로 사용될 때

홀로 사용된 thisglobal object(전역 객체)를 참조한다. global object는 브라우저상에서는 window, nodejs에서는 global 객체를 의미한다. 전역 객체에는 전역 변수, 전역 함수등이 프로퍼티, 메소드로 존재한다.

스크린샷 2023-07-27 오후 10.50.57.png 크롬의 개발자도구 콘솔에서 this를 출력해본 모습

함수 내부

함수 내부에서도 홀로 사용될 때와 동일하게 global object를 참조한다. 단, strict mode에서 thisundefined이다.

"use strict";
function myFunction() {
  return this;
}

console.log(myFunction()); // undefined

고차 함수의 콜백함수 내부

고차 함수란 함수를 인자를 받거나 함수를 반환함으로써 작동하는 함수이다.

고차 함수의 콜백함수 안에서 this 는 콜백함수가 객체의 메소드가 아닌 일반 함수이기 때문에 global object를 참조한다.

const fn = {
  title: "Hello World!",
  tags: [1, 2, 3, 4],
  showTags() {
    this.tags.forEach(function (tag) {
      console.log(tag);
      console.log(this); // window
    });
  },
};

만약 이 경우에 this 가 fn을 참조하게하고 싶다면 어떻게 해야할까?

const fn = {
  title: "Hello World!",
  tags: [1, 2, 3, 4],
  showTags() {
    this.tags.forEach(function (tag) {
      console.log(tag);
      console.log(this); // fn
    }, this); // 여기는 일반 함수 바깥, fn 객체를 참조할 수 있다.
  },
};

이렇게 콜백함수의 다음 인자로 this (여기서 this는 객체의 메소드 내부이므로 해당 객체인 fn을 참조한다)를 넘겨주면 콜백함수의 인자로 들어가게된다.

화살표 함수 내부

콜백 함수로 function 키워드를 통해 생성한 일반함수를 넘겼을때 해당 함수 내에서의 this는 global object를 참조했다. 하지만 화살표 함수로 콜백함수를 넘겼을 때, this는 상위 스코프의 this를 가리키게 된다. 이것이 function 키워드를 통해 생성한 일반함수와 화살표함수의 가장 큰 차이점이다.

const fn = {
  title: "Hello World!",
  tags: [1, 2, 3, 4],
  showTags() {
    this.tags.forEach((tag) => {
      console.log(tag);
      console.log(this); // fn
    });
  },
};

이 화살표 함수 안의 thisLexical this 라고 한다. 일반 함수의 this 는 함수를 선언할 때 this 에 바인딩될 객체가 정적으로 결정되지 않고, 함수를 호출할 때 함수가 어떻게 호출되는지에 따라 동적으로 결정된다.

하지만 화살표 함수의 this 는 함수가 선언될 때 상위 스코프의 this 로 정적으로 결정된다. 이 화살표 함수의 this 는 아래에 나올 call, apply, bind 메소드를 사용해도 참조할 객체를 변경할 수 없다.

Event Handler 내부

HTML의 이벤트 핸들러 내부에서, this 는 이벤트를 받은 해당 HTML element를 참조한다.

<button onclick="this.style.display='none'">Click to Remove Me!</button>

위 예시에서 this 는 onclick 이벤트를 받는 해당 button element를 참조한다.

call(), apply(), bind()

위 세함수를 이용해 함수 내부의 this를 다른 객체를 참조하도록 만들 수 있다. 예를 들어 call 메소드의 경우를 살펴보자.

call()

사용법 : fun.call(thisObj, arg1, arg2, …, argN);

fun : 가져다 사용할 메소드

thisObj(optional) : this가 참조할 객체

arg1, arg2, …, argN(optional) : 메소드 fun에 전달될 인수 목록

type = "zero";
const type1 = { type: "one" };
const type2 = { type: "two" };

function getType() {
  console.log(this.type);
}

getType(); // zero
getType.call(this); // zero
getType.call(type1); // one
getType.call(type2); // two

getType 함수 내부의 this는 원래 global object를 참조하므로 getType() 실행 시 window.type이 출력된다.

getType.call(this)의 this도 동일하게 global object를 참조하므로 window.type이 출력되지만, call의 첫번째 인자인 thisObj에 type1과 type2를 넘긴 경우에는 this가 각각 type1가 type2를 참조하게 되어 type1.type과 type2.type이 출력되게 된다.

apply()

사용법 : fun.apply(thisObj, [argArray]);

apply 메소드는 call 메소드와 동일하지만, call 메소드는 arg1, arg2, …, argN처럼 인자 하나하나를 전달하고, apply 메소드는 인자 리스트 한 개를 전달한다는 차이만 존재한다.

bind()

bind 메소드도 call, apply 메소드와 비슷하지만, bind 메소드는 함수 내의 this 가 참조하는 객체만 바꾸고 함수를 호출하지는 않는다.

type = "zero";
const type1 = { type: "one" };

function getType() {
  console.log(this.type);
}

const test = getType.bind(type1);
test(); // one

bind 메소드를 통해 getType함수의 this 의 참조 객체가 type1으로 설정되었지만, 바로 실행되지 않고 함수만 반환되었다. 이후 test()를 통해 실행해보면 type1.type의 값이 잘 출력된다.

체이닝

객체의 메소드에서, 해당 객체인 this를 리턴하면 연속으로 함수호출이 가능하다.

let ladder = {
  step: 0,
  up() {
    this.step++;
    return this;
  },
  down() {
    this.step--;
    return this;
  },
  showStep() {
    alert(this.step);
  },
};

ladder.up().up().down().up().down().showStep();

참고 내용

JavaScript this

Global object - MDN Web Docs Glossary

[JS] 📚 자바스크립트 this 💯 완전 정복

[JavaScript] this 란 무엇일까? - 하나몬

[자바스크립트] API - call, apply 함수

Tags: ,

Categories:

Updated:

Leave a comment