React 라이브러리

8 . Component 클래스에서 메소드의 2가지 형태의 차이점( 화살표 함수, 일반 함수 형태)

문정훈 2021. 11. 13. 02:26

클래스로 작성된 컴포넌트에서 왜 일반 함수를 사용하기 보다 화살표 함수가 사용되는지 정리해보았다.

 

 

선행 개념1) 메소드란?

js에서 함수와 메소드의 차이점을 보면 메소드란 객체에 바인딩된 함수를 일컫는 의미로 ES6에서는 메소드를 다음과 같이 정의한다. "메소드란 메소드 축약 표현으로 정의된 함수만을 의미한다."

위 정의를 좀 더 확장해서 정리해보면

  1. 우선 메소드는 non-constructor하다. (생성자 함수로 호출 불가능)
  2. prototype 프로퍼티가 없으며 프로토타입 역시 생성하지 않는다. 
var obj = {
  value : 1,
  objFunc() { //객체 리터럴에 선언된 메소드
    console.log(">>"+this); //obj에 바인딩	
    function func4() {//메소드 안에 선언된 함수
        console.log(">>"+this); //this는 window
      }
      func4();
  }
}

obj.objFunc()

//실행 결과
//>>[object Object]
//>>[object global]

위 코드를 다시 보면 objFunc은 함수가 아니라 메소드이다.

메소드에 선언된 this는 자신을 선언한 객체인 obj에 할당된다.

메소드 내부에 선언된 func4는 함수이다. 어떠한 경우(메소드 내부, 콜백함수, 중첩함수) 이건 함수에서의 this는 window에 바인딩된다. 

 

 

선행개념2) js에서 이벤트로 전달된 값

<button onclick ="func1()">버튼</button>

위와 같이 onclick이벤트로 전달된 함수는 아래와 같이 처리된다. 

function onclick(event) {
	func1();
}

 

 


 

 

단순히 화살표 함수의 개념을 정리하는 것보다 react를 공부하며 화살표 함수가 실제로 왜 등장하게 되었는지 몸소 느낀점을 정리했다..

이 절을 읽기 전에 js에서 '메소드'와 '함수'가 어떻게 다른지와 일반 함수에서 this 할당 그리고 메소드에서 this 할당이 어떻게 다른지 알아야한다. (바로 위에 선행 개념1, 2를 알고 읽을 것을 권장) 

 

화살표 함수에 대해 간단히 설명하면

우선 화살표 함수는 non-constructor이며 (생성자 함수로 객체를 생성할 수 없다.)  prototype 프로퍼티가 없다. 즉 프로토타입을 생성하지 않는다. 

 

화살표 함수가 등장한 이유는 콜백 함수 내에서 this가 전역 객체에 바인딩 된다는 문제점을 해결하기 위해 나왔다. 

화살표 함수의 this바인딩은 화살표 함수가 선언된 상위 스코프이다.

 

class App extends React.Component {
    state = {...}
    
    func1() {
    	console.log(this); // this는 App를 가리킴
    }
}

위 클래스 내부의 func1는 함수가 아닌 메소드이다. 위와 같은 메소드에서 this는 당연히 클래스에 바인딩 된다.

(참고로 만약 func1 메소드 내부에 func2라는 "함수"가 선언된다면 함수 내부에서 this는 -> window에 바인딩이다.)

이제 아래 코드를 보자

 

 

class App extends React.Component {
	state = {...}
    
    func1() {
    	console.log(this); // this는 App를 가리킴
    }
    
    render() {
    	return (
            <div>
            	<button onClick = {this.func1}>클릭함</button>
            </div>
        )
    }
}

위 코드에서 App의 메소드인 func1()을 그냥 호출한다면 this는 App에 바인딩이 된다. 하지만

onClick 클릭했을 때 호출되는 func1 내부의 console.log(this) 코드의 this가 window에 바인딩된다는 문제점이 발생한다.

onClick의 값으로 전달하는 함수는 선행개념2에서 알 수 있듯이 콜백함수가 아니다.!! (만약 콜백함수 였다면 window 바인딩이 당연한데..)

그 이유는 아래와 같다고 추측한다.  아래 예시를 보자

 

예시) 

const obj = new Object();

obj.method1 = function() {
  console.log(">>"+this)
}

obj.method1();

const a = obj.method1

a();

//결과값
//>>[object Object]
//>>[object global]

위 코드를 실행해보면 위와 같은 결과가 나온다.

위 코드는 a = funciton() { console.log(">>" + this) } 

이것을 의미한다고 생각하면 된다.

 a = funciton() { console.log(">>" + this) }  이 코드만 봤을 때 this는 당연히 window에 할당된다는 것을 알 고 있다. 

(일반 함수의 this는 window에 할당된다.)

 

react 내부적으로 위 예시와 같은 동작을 수행하였다고 추측한다. 따라서

onclick의 값으로 전달된 메소드는 콜백함수가 아님에도 불구하고 func1 내부의 this가 window에 바인딩된다.

이러한 문제점 때문에 react에서 컴포넌트(클래스 컴포넌트)에서 메소드는 화살표 함수로 선언하는 것이 일반적이다. 

화살표 함수는 내부적으로 this의 바인딩이 존재하지 않는다.

따라서 화살표 함수에서 this호출은 화살표 함수의 상위 스코프의 this값을 읽게 된다. 

즉 화살표 함수에서의 this는 화살표 함수가 정의된 상위 스코프이다.!!!