본문 바로가기
FrontEnd/Java Script

[this] 5년만에 다시보는 자바스크립트의 this

by Fathory 2024. 8. 28.

개요

많은 시간이 지나고 나는 this가 지칠하는게 뭔지 잘 알고있는가에 대해서 물어봤을때 잘 모르는게 맞다! 라는 판단이 들었다.
그 이유는 면접에서 털렸기때문이다 

예제를 보다 구체적으로 알아보면서 컨텍스트에 따라서 this가 어떤 객체를 가리키는가에 대해서 한번 더 알아보고자 한다.

 

1. 글로벌 컨텍스트

 

  • 글로벌 컨텍스트에서 this는 전역 객체를 가리킵니다.
  • 브라우저 환경에서는 window 객체를, Node.js 환경에서는 global 객체를 참조합니다.

 

// 글로벌 컨텍스트
console.log(this); // 브라우저에서는 'window' 객체, Node.js에서는 'global' 객체

const person = {
  name: 'Alice',
  greet: function() {
    console.log(this); // 'person' 객체
    console.log('Hello, my name is ' + this.name);
  }
};

person.greet(); // 출력: 'person' 객체, 'Hello, my name is Alice'

// 브라우저
console.log(this === window); // true

// Node.js
console.log(this === global); // true

 

2. 객체 메서드

 

  • greet 메서드에서 this는 person 객체를 가리킵니다.
  • 이는 메서드가 호출될 때, 메서드가 속한 객체를 this로 참조하기 때문입니다.
const person = {
  name: 'Alice',
  greet: function() {
    console.log(this); // 'person' 객체
    console.log('Hello, my name is ' + this.name);
  }
};

person.greet(); // 출력: 'person' 객체, 'Hello, my name is Alice'


// 만약 다른 객체에 이 메서드를 할당하면, this가 달라짐
const anotherPerson = { name: 'Bob' };
anotherPerson.greet = person.greet;
anotherPerson.greet(); // 출력: 'Bob'

 

 

3. 일반함수

  • sayHi 메서드 내에서 this.name은 user 객체의 name 프로퍼티를 참조합니다.
  • 하지만 setTimeout 안에서의 this는 전역 객체를 참조하게 됩니다. 브라우저에서는 window, Node.js에서는 global이 됩니다.
  • 따라서 window.name이나 global.name이 정의되지 않았다면 undefined가 출력됩니다.
const user = {
  name: 'Bob',
  sayHi: function() {
    console.log(this.name); // 'Bob'
    setTimeout(function() {
      console.log(this.name); // 'undefined' (일반 함수의 this는 글로벌 객체를 참조함)
    }, 1000);
  }
};

user.sayHi();


// 'this'를 변수에 저장하거나, 화살표 함수 사용하면 일반함수의 This가 undefined로 지칭되는 것을 방지할 수 있음
const user = {
  name: 'Bob',
  sayHi: function() {
    const self = this; // 'this'를 변수에 저장
    setTimeout(function() {
      console.log(self.name); // 'Bob'
    }, 1000);
  }
};

user.sayHi();

 

4. 화살표 함수

 

  • 화살표 함수는 this를 자신을 둘러싼 상위 스코프의 this와 바인딩합니다.
  • 여기서는 sayHello 메서드 내의 this가 user2 객체를 가리키므로, setTimeout 내에서도 동일하게 user2를 참조합니다.

 

const user2 = {
  name: 'Charlie',
  sayHello: function() {
    console.log(this.name); // 'Charlie'
    setTimeout(() => {
      console.log(this.name); // 'Charlie' (화살표 함수는 상위 스코프의 this를 참조)
    }, 1000);
  }
};

user2.sayHello();

// 화살표 함수와 일반 함수의 차이점
const example = {
  name: 'Example',
  normalFunc: function() {
    return function() {
      console.log(this.name); // 전역 객체 참조
    };
  },
  arrowFunc: function() {
    return () => {
      console.log(this.name); // 'Example' 참조
    };
  }
};

example.normalFunc()(); // undefined
example.arrowFunc()(); // 'Example'

 

5. 생성자 함수

 

  • 생성자 함수 Person을 new 키워드와 함께 호출하면, this는 새로 생성된 객체를 참조합니다.
  • 이 객체의 name 프로퍼티는 생성자 함수 내부에서 this.name = name을 통해 설정됩니다.
function Person(name) {
  this.name = name;
}

const person1 = new Person('David');
console.log(person1.name); // 'David'

const person2 = new Person('Eve');
console.log(person2.name); // 'Eve'

// 생성자 함수는 여러 객체를 쉽게 생성하는 데 유용
const person3 = new Person('Frank');
console.log(person3.name); // 'Frank'

 


6. 클래스

 

  • 클래스에서 this는 해당 클래스 인스턴스를 참조합니다.
  • speak 메서드는 인스턴스의 name 프로퍼티를 사용하여 메시지를 출력합니다.
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

const animal = new Animal('Lion');
animal.speak(); // 'Lion makes a noise.'



const anotherAnimal = new Animal('Elephant');
anotherAnimal.speak(); // 'Elephant makes a noise.'

// 클래스 메서드는 인스턴스에 고유한 동작을 정의

 

 

 

다시 봐도 헷갈리는 this.
아주 기본적이고, 반드시 알아야하는 중요한 개념이니 다시 한 번 잘 익혀두도록 하자
반응형