일반 함수 vs 화살표 함수

윤한영·2024년 10월 25일
0

React

목록 보기
10/10
post-thumbnail

평소와 같이 개발을 하다가

Uncaught TypeError: Cannot read properties of undefined (reading 'setState') ....
이런 에러를 만나게 되었다..?

undefined의 property를 읽을 수 없다는 거 같은데...
오류가 나는 코드를 보니 this.setState({ … }); 처리하는 부분이 있었고, 이 부분에서 this가 컴포넌트를 가르키고 있지 않는 것을 확인할 수 있었다

this.setState({…}) 를 할 때 this 가 컴포넌트를 가르키고 있지 않았던 것

아래 코드 부분입니다 !

위의 코드처럼 객체의 메서드로 일반 함수를 만들어 this를 찍어서 사용하면 그 객체(=getMainButtons)를 가르키게 된다.



해결방법은

일반 함수 형태로 선언되어 있는 getMainButtons()화살표 함수 형태로 만들어주면 된다.

가려져 있지만..

getMainButtons() { … }	->	getMainButtons: () => { … }
// 이렇게 수정하면 해결이 됩니다. 

this에 대해서 어렴풋이 알고는 있었지만 확실히 알아보기 위해서 예시를 만들어서 테스트 해보았습니다.



일반 함수와 화살표 함수가 가리키는 this는 어떻게 다를까?

이 부분을 알아보려면 켄텍스트 라는 개념을 알아야 합니다.


  • 컨텍스트 or 실행컨텍스트란?

    프로그래밍에서 특정 코드 블록이나 함수가 실행될 때, 그 코드가 어떤 환경에서 실행되고 있는지를 나타내는 개념.
참고... https://heycoding.tistory.com/86

함수 컨텍스트

함수가 호출될 때 생성되는 컨텍스트.

  • 일반 함수의 경우, 호출된 방식에 따라 this가 다르게 설정됨.

    객체의 메서드로 호출되면 this는 그 객체를 가르키고, 일반 함수로 호출되면 전역 객체를 가리키거나 undefined가 됨.
/* ----------- 객체의 메서드로 호출되는 예시 --------- */
const person = {
  name: 'Han0',
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

// 메서드로 호출
person.greet(); // 출력: Hello, my name is Han0

  • 화살표 함수의 경우, 자신이 정의된 위치의 컨텍스트를 그대로 사용. 화살표 함수가 정의된 곳의 this를 참조함.

    화살표 함수(=greet)가 정의된 곳(=person)의 this를 참조하게 됩니다.
/* ----------- 객체의 메서드로 호출되는 예시 --------- */
this.name = '한영'
const person = {
  name: 'YoonHan0',
  greet: () => {
    console.log(`Hello, my name is ${this.name}`);
  }
};

// 메서드로 호출
person.greet(); // 출력: Hello, my name is 한영


아래에는 일반 함수, 화살표 함수를 비교하기 위해 만들어본 예시입니다 !

import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);

    // 일반 함수 바인딩
    this.handleIncrement = this.handleIncrement.bind(this);
    /* bind 하지 않으면
    Uncaught TypeError: Cannot read properties of undefined (reading 'setState') .... 에러 발생
     */
  }
  state = {
    count: 0,
  }

  // 일반 함수
  // 일반 함수는 호출되는 컨텍스트에 따라 this가 결정됨
  handleIncrement() {
    // 여기서 this는 undefined가 될 수 있습니다.
    console.log(this); // undefined (strict mode에서)
    this.setState({ count: this.state.count + 1 });
  }

  // 화살표 함수
  // 화살표 함수는 자신이 정의된 컨텍스트의 this를 그대로 사용
  handleDecrement = () => {
    // 여기서 this는 MyComponent 인스턴스를 가리킵니다.
    console.log(this); // MyComponent { ... }
    this.setState({ count: this.state.count - 1 });
  };

  // 위의 일반 함수, 화살표 함수를 테스트하는 함수
  testFunc = () => {
    this.name = '한영';
    const person = {
      name: 'Han0',
      greet: function () {
        console.log(`Hello, my name is ${this.name}`);
      }
      /*
      greet: () => {
        console.log(`Hello, my name is ${this.name}`);
      }
      */
    };
    person.greet();
  }

  render() {
    return (
      <div>
        <h1>Count: {this.state.count}</h1>
        <button onClick={this.handleIncrement}>Increment</button>
        <button onClick={this.handleDecrement}>Decrement</button>
		<button onClick={this.testFunc}>HELLO</button>
      </div>
    );
  }
}

export default MyComponent;



이미지 출처
https://velog.io/@rlacksals96/CS-Javascript-This

0개의 댓글