My Boundary As Much As I Experienced

JS) this란 무엇인가? 본문

FrontEnd/Javascript(Vanilla)

JS) this란 무엇인가?

Bumang 2023. 7. 21. 11:28

this라는 이 오묘한 녀석... 문맥에 따라 달라지는 한국어같은 녀석이다.

왜 자바스크립트는 이렇게 맥락적인 문법을 만들었을까?

쓰임새가 딱 한 가지로 고정되어 있는 문법 여러 개가 있는게 더 낫지 않을까.

 

면접을 위해 한 마디로 요약하자면:

This는 쓰이는 위치에 따라 다르게 정의되지만, 주로 쓰이는 방식은 함수 객체나 클래스의 패러미터로 받아 그 값을 지정할 때 많이 씁니다. 기본적으로 메소드 안에 쓰일 땐 호출한 대상에게 바인딩되고 일반 함수에서 쓰일 땐 그 함수의 한 단계 상위 스코프에 바인딩 됩니다. 화살표 함수로 쓰일 땐 자신이 선언된 함수의 유효 범위에 정의됩니다. 

 

This의 쓰임새

일반 함수에서 쓰일 때: 함수의 주인에게 바인딩

메소드에서 쓰일 때: 호출 위치에서 정의(this 포함된 스코프)

화살표 함수에서 쓰일 때: this는 자신이 선언된 함수(렉시컬) 범위에서 정의

*렉시컬(lexical)이란 함수가 동작할 수 있는 유효한 범위를 의미한다.

 

 

일반 함수에서 쓰일 때

함수 안에서 this는 함수의 주인에게 바인딩된다.

함수의 주인은? 브라우저 상에선 window이다.

function myFunction() {
  return this;
}
console.log(myFunction()); //Window

 

만약 전역 변수를 이렇게 반환하라고 해도 무리없이 반환해준다. 이때 this는 window니까.

const randomName = "muyaho"

function myFunction() {
  return this.randomName
}
console.log(myFunction()); //muyaho

 

 

객체 내 메소드 안에서 쓰일 때

const user = {
  firstName: "Bumang",
  lastName: "Jiong",
  age: "27",
  getFullName: function () {
    return `${this.firstName} ${this.lastName}`;
    //해당하는 객체 데이터 내의 것을 참조...
  },
};

console.log(user.getFullName());
// "Bumang Jiong"

같은 객체 안의 스코프를 탐색하여 해당하는 프로퍼티를 참조해온다.

 

 

this는 자신이 속한 함수의 주인을 탐색한다.

function homura() {
  this.firstName = "Homura";
  this.lastName = "Akemi";
  return {
    firstName: "Mami",
    lastName: "Tomoe",
    age: "15",
    getFullName() {
      return `${this.firstName} ${this.lastName}`;
    },
    // 자신이 속한 객체 데이터에서 탐색한다.
    // Mami Tomoe 반환
  };
}

위 예시는 객체 안의 메소드에 this가 쓰인 케이스이다.

이때 this는 자신(메소드)이 속한 주인인 객체 데이터를 참조한다.

자신이 속한 메소드를 호출하는 객체에 바인딩된다.

 

 

 

메소드 내 화살표 함수 안에 this를 사용할 때

function homura() {
  this.firstName = "Homura";
  this.lastName = "Akemi";
  return {
    firstName: "Mami",
    lastName: "Tomoe",
    age: "15",
    getFullName: () => {
      return `${this.firstName} ${this.lastName}`;
    },
    // 화살표 함수일 때는 자신이 선언된 블록을 감싸는 상위 함수(?)를 참조.
    // getfullName을 감싸는 함수는 존재하지 않으면 undefined undefined가 뜸.
  };
}

화살표 함수를 사용하면 자신이 속해있는 함수 전역을 기준으로 작동하게 된다. (왜냐고? 계속 탐구해야될 숙제다...)

직속 주인님이 아니라 함수 주인님을 찾는다(!)

this 자신이 속한 객체에서 Mami Tomoe를 찾는게 아니라, 자신이 속해있는 가장 상위 함수 기준으로 탐색을 하여 반환한다.

 

 

 

call() 등으로 다른 객체를 대상으로 활용될 때

const user = {
  firstName: "Bumang",
  lastName: "Jiong",
  age: "27",
  getFullName: function () {
    return `${this.firstName} ${this.lastName}`;
    //해당하는 객체 데이터 내의 것을 참조...
  },
};

const lewis = {
  firstName: "Lewis",
  lastName: "yang",
};

console.log(user.getFullName.call(lewis));
// lewis yang

user에 있는 getFullName 메소드를 .call() 메소드를 통해 lewis 객체를 대상으로 실행시킨다.

그러면 lewis 객체의 firstName과 lastName을 참조하여 lewis yang이라는 결과가 나온다.

이 또한, 자신이 속한 메소드를 호출하는 객체에 바인딩 된다고 볼 수 있다.

 

 

일반 함수의 this 참조 특성과 화살표 함수의 this 참조 특성을 이용한 사례

const timer = {
  title: "TIMER!",
  timeout() {
    console.log(this.title);
    setTimeout(() => {
      console.log(this.title);
    }, 1000);
    // 여기서 익명 함수를 쓰면 렉시컬 내에 title이 없으므로 undefined가 뜬다.
    //그러나 화살표 함수를 쓰면 함수전역 스코프가 기준이므로 TIMER!가 잘 뜬다.
  },
};

이 함수의 timeout 메소드를 보면 첫 콘솔 로그는 익명함수 내에서, setTimeout함수 안에선 또 화살표 함수를 쓴 것을 볼 수 있다.

setTimeout 안의 함수를 익명 함수로 만들었다면? undefined가 표출되었을 것이다.

setTimeout 상에서는 title 프로퍼티가 없기 때문이다.

 

그러나 함수 전역을 참조하는 화살표 함수의 특성 상, 함수 내의 this가 가르키는 title 프로퍼티를 제대로 가져온다.

'FrontEnd > Javascript(Vanilla)' 카테고리의 다른 글

콜백함수  (0) 2023.08.01
JS) 프로토타입(Prototype)  (0) 2023.07.22
JS) 화살표 함수  (0) 2023.07.21
JS) 호출 스케줄링  (0) 2023.07.20
JS) 매개변수 패턴(Parameter Pattern)  (0) 2023.07.20