티스토리 뷰

function 함수

function func(){
}

화살표 함수

const func2=()=>{}

 

 

function 함수와 화살표 함수의 차이점

function 함수에서는 prototype이 있고, 화살표 함수에는 없습니다. 따라서 더 가볍게 사용할 수 있고, 본래 함수의 역할이 아닌 생성자로 사용할 수 없습니다.

 

또한 화살표 함수는 caller와 arguments가 감싸져 있어 getter로 불러와야 한다는 특징이 있습니다.

 

그리고 화살표 함수는 this를 바인딩하지 않는다는 특징이 있습니다.  원래 함수의 역할로 사용한다고 하면 this를 사용해야 할 필요가 없습니다. this를 사용해야 할 경우에는 class 혹은 객체 메서드 선언 방식을 통해 사용하면 되겠습니다. 따라서 함수를 사용할 때에는 더 가벼운 화살표 함수를 사용하면 되겠습니다.

 

화살표 함수의 장점

  • this를 신경 쓰지 않아도 되기에 순수 함수로 사용할 수 있다.
  • function은 일반 함수, 생성자 함수, 메서드 함수의 다양한 역할을 하지만 화살표 함수를 사용하면 '이 코드는 함수다'라는 정보를 다른 개발자에게 명확히 전달할 수 있다.
  • function과 달리 프로토타입이 없기에 더 가볍다

 

도움 받은 자료

 


ES6 클래스, 객체에서도 화살표 함수를 쓰면 되나요?

 

이렇게 생각하실 수도 있습니다. 저는 그렇게 생각이 들어 궁금해졌었습니다. 

 

ES6 클래스

대부분의 라이브러리, 예시 코드에서 메서드를 선언할 때 function처럼 일반 메서드 선언으로 사용합니다. 그래서 저도 대다수의 규칙을 따르고자 클래스에서 function으로 사용했습니다. 하지만 검색을 통해 찾아보니 클래스에서 화살표 함수를 잘 사용하지 않는 이유는 화살표 함수를 사용하면 상속했을 때 super. 화살표 함수명() 이 작동이 되지 않는다고 합니다. 

 

바벨에서 테스트해 볼 수 있습니다.

 

Babel · Babel

The compiler for next generation JavaScript

babeljs.io

바벨을 거치기 전 코드

class A {
  static color = "red";
  counter = 0;

  handleClick = () => {
    this.counter++;
    console.log("A.handleClick");
  }

  handleLongClick() {
    this.counter++;
  }
  
}

 

바벨을 거친 후 코드

class A {
  constructor() {
    this.counter = 0

    this.handleClick = () => {
      this.counter++
      console.log("A.handleClick");
    }
  }

  handleLongClick() {
    this.counter++
  }
}

 

console.dir을 해본 결과

A의 코드

class A {
  static color = "red";
  counter = 0;

  handleClick = () => {
    this.counter++;
    console.log("A.handleClick");
  }

  handleLongClick() {
    this.counter++;
  }
  
}

A의 프로토타입에는 handleLongClick 만 있을 뿐 handleClick은 찾아볼 수 없었습니다. 반면에 new A()를 해보았을 때 생성자로 생긴 counter와  handleClick을 찾아볼 수 있었습니다. 

 

즉, handleClick는 프로토타입에 정의된 메서드가 아니라 실제로 클래스의 인스턴스 속성입니다.

 

 

B의 코드

class B extends A {
 
}

클래스 B가 클래스 A에서 상속되는 일반 클래스인 경우, 그는 빈 프로토타입을 갖게 되고  B.handleClick()은  A.handleClick()이 됩니다. 


이 코드는 handleClick 메서드가 프로토타입이 아닌 A의 인스턴스에 정의되어 있기 때문에 작동합니다. B는 A를 확장할 때 handleClick 인스턴스 속성도 상속합니다.

B의 새 인스턴스를 만들고 handleClick를 호출하면 B의 인스턴스에서 handleClick 인스턴스 속성을 찾습니다. B는 자체 handleClick 인스턴스 속성을 정의하지 않으므로 A에서 handleClick 인스턴스 속성을 상속합니다.

 

 

C의 코드

class C extends A {
  handleClick = () => {
    super.handleClick();

    console.log("C.handleClick");
  }

  handleLongClick() {
    super.handleLongClick();

    console.log("C.handleLongClick");
  }
}

console.log(C.prototype);
// A {constructor: ƒ, handleLongClick: ƒ}

console.log(C.prototype.__proto__);
// {constructor: ƒ, handleLongClick: ƒ}

new C().handleClick();
// Uncaught TypeError: (intermediate value).handleClick is not a function

new C().handleLongClick();
// A.handleLongClick
// C.handleLongClick

 

 

클래스 A를 클래스 C로 확장하고 handleClick을 handleClick=()=>{} 구문을 사용하여 C에서 화살표 함수로 정의하면 C 클래스에 handleClick라는 새 인스턴스 속성이 생성됩니다. 이 속성은 A의 프로토타입에 정의된 handleClick 메서드보다 우선합니다. 이때 C의 화살표 함수 안에서 super.handleClick()를 호출하면 super 때문에 오류가 발생합니다.

 

C의 handleClick메서드 안에서 super.handleClick()를 호출하면 A의 프로토타입에서 handleClick 메서드를 찾습니다. 하지만 handleClick는 A의 프로토타입에 정의되어 있지 않기 때문에 super.handleClick가 정의되지 않았으며 함수로 호출하면 TypeError가 발생합니다.

 

\

 

D의 코드

class D extends A {
  handleClick() {
    super.handleClick();

    console.log("D.handleClick");
  }
}

console.log(D.prototype);
// A {constructor: ƒ, handleClick: ƒ}

console.log(D.prototype.__proto__);
// {constructor: ƒ, handleLongClick: ƒ}

new D().handleClick();
// A.handleClick

클래스 D가 클래스 A를 상속받고 일반 메서드로 handleClick을 선언하였습니다. handleClick은 super.handleClick()만 실행하고 다른 것은 실행하지 않습니다. 이상하지 않나요?


이는 부모 클래스 A의 handleClick 메서드가 D 클래스에서 재정의되지 않았기 때문입니다.

 

자식 클래스에서 메서드를 선언할 때, 함수 선언식을 사용하면 해당 메서드가 클래스의 프로토타입에 추가되기 때문입니다.


D 클래스에서 함수 선언식으로 handleClick 메서드를 정의할 경우, 부모 클래스의 handleClick 메서드를 덮어쓰지 않고, 부모 클래스의 handleClick 메서드가 그대로 호출됩니다. 하지만 화살표 함수로 handleClick 메서드를 정의할 경우, 자식 클래스의 인스턴스를 참조하는 this를 가지므로, 부모 클래스의 handleClick 메서드를 덮어쓰고, 자식 클래스에서 정의한 handleClick 메서드가 호출됩니다.

 

 

 

 

new D(). handleClick이 A의 handleClick 메서드만 동작하는 이유

예시 코드

함수 선언식으로 handleClick을 정의하여  D의 프로토타입에 handleClick가 추가되었습니다. 이때 new D(). handleClick()을 하게 되면 인스턴스 생성자 함수 먼저 실행하기에 기존의 A의 handleClick만 실행이 되는 모습입니다.

 

 

결론

클래스에서는 선언식을 사용하도록 합시다. 이유는 덮어씌우는 것을 따로 생각해야 해서 개발자가 의도한 것과 다른 동작이 일어날 수 있습니다. 클래스에서는 속도 또한 일반 함수 선언식이 화살표함수보다 더 빠르다고 합니다.

 

저의 경우는 객체(오브젝트) 메서드 형식으로는 this가 필요한 상황이 아니라면 객체로 만들지 않고 화살표 함수로 만들어 각각 사용하려고 합니다. 그리고 this가 필요하다면 클래스로 만들어 일반 함수 선언식을 사용하도록 하겠습니다.

 

일반 함수 선언식이 화살표함수보다 더 빠르다

 

 

 

참고

 

[번역] 클래스 프로퍼티로 화살표 함수 사용하는 것은 생각만큼 좋지않다

리액트에서 클래스 컴포넌트를 사용하다가 arrow function과 메서드 차이가 궁금해져서 찾아본 포스팅이다. Class Properties Proposal 덕분에 코드가 간단해졌는데, 특히 내부 나 와 를 static으로 작성할

hoilzz.github.io

 

Arrow Functions in Class Properties Might Not Be As Great As We Think

Since the last year, the Class Properties Proposal simplify our life, especially in React with the internal state , or even with statics…

medium.com

 

 
 
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함