ES6 함수의 추가 기능 


ES6 이전까지의 자바스크립트의 함수는 별다른 구분 없이 사용되었다고 한다. 모든 함수는 callable하면서 constructor였다는 것.

ES6 전부터 코딩을 해온게 아닌 나로써는 정확히 어떤 의미인지는 알기 쉽지 않지만...

보기에는 하나의 함수로 모든 것을 할 수 있으니까 편해보일 수 있으나 이런 특성은 실수를 유발하고 성능적인 면에서 손해라는 것이다.

예를 들어서 메소드를 new  연산자와 함께 생성자 함수로써 호출할 수 도 있는데 이렇게 되면 메소드에도 프로토타입 프로퍼티를 가지게되고 프로토타입 객체또한 생성한다는 것을 의미하니까, 불필요한 것들을 생산한다고 볼 수 있는거죠. 

 

그래서 함수를 ES6부터는 3가지로 분류를 하였는데,

ES6 함수의 구분  constructor prototype super arguments
일반함수  O X O
메소드 X X O O
화살표 함수 X X X X

여기서 제일 중요한 포인트는 일반함수만 contructor라는 것이고, 메소드와 화살표 함수는 non-constructor 라는 것이다.

 


메소드 

ES6에서 부터 메소드는 메소드 축약 표현으로 정의된 함수만을 의미한다. 

 

메소드의 예와 아닌 예

 

 

그리고 ES6 메소드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는데, 이를 가지고 있어야 super 키워드를 사용할 수 있다. 왼쪽에서 보면 주석으로 잘 설명이 되있겠지만 derived 객체에서 작성된 sayHi 메소드는 [[HomeObject]]가 derived일 것이고, 당연히 그 메소드의 return으로 호출한 super.sayHi()는 [[HomeObject]]가 base를 가르킬거다. 

 

 

 


화살표 함수 

function 키워드 대신 화살표(=>, fat arrow)를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의할 수 있다. 
콜백 함수 내부에서 this가 전역 객체를 가르키는 문제를 해결하기 위한 대안으로 유용하다. 

일단 화살표 함수는 무조건 함수 표현식으로 정의를 해야한다. 

 

 

객체 리터럴을 반환하는 경우는 소괄호로 감싸 주어야한다. 

 

 

 

즉시 실행 함수로도 사용이 가능하다. 

 

나머지는 사용하면서 알게된 너무 당연한 특징이였고 생소했던 3가지를 적어보았다. 

 

 

화살표 함수와 일반 함수의 차이 

 

1. 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor다.

   ES6로 바뀌면서 화살표 함수가 새로 등장하고, 기존에 있던 메소드는 constructor를 가질 수 없게끔 개편되었다.

   이유는 앞서 말했다 싶 이 인스턴스를 생성할 수도 없고하니 필요도 없는 걸 생성하면 성능적으로 낭비이기 때문이다. 

 

2. 중복된 매개변수 이름을 선언할 수 없다. 

   일반 함수에서는 strict mode에서만 중복 매개변수에 대해 에러를 일으키는데, 화살표함수는 그마저도 필요없는 것이다. 

   개인적으로 애초에 중복 매개변수를 받는 거 자체가 좋아 보이진 않는다.

 

 

3. 화살표 함수는 함수 자체의 this, arguments, super, new target 바인딩을 갖지 않는다. 

   화살표 함수 내부에서 this, arguments, super, new.target을 참조하면 스코프 체인을 통해 상위 스코프를 참조한다. 

   만약에 상위 스코프가 화살표 함수라면 그나마 더 가까운 화살표 함수가 아닌 함수를 참조한다고 한다. 

 


this

화살표 함수의 this와 일반 함수와 this는 다르게 동작한다. 콜백 함수 내부의 this 문제를 해결하기 위해 의도적으로 설계가 된 것이다. 

 

콜백 함수의 this 문제의 예

왼쪽 코드를 보면 클래스 prefixer.add를 통해 배열을 인자로 넣어서 호출하고 그 뒤 map 메소드를 통해 prefix인 'use'와 매개변수를 하나씩 붙여줘서 출력이 ['useState', 'useEffect'] 가 예상 출력인데 왼쪽 코드는 에러가 난다. 이유가 뭘까 ?  앞에서도 언급한 "콜백 함수 내부의 this 문제" 에 대해 다시보아야 한다. 함수가 어떻게 호출되는지에 따라 this는 동적으로 결정되는건 알고 있을건데, 물론 add 메소드 안에서 this는 호출한 객체인 prefixer 객체를 가르키지만 이때 map함수의 인수로 전달한 콜백함수가 add 메소드의 내부인 상태에서 일반 함수로 호출이 된다. 이렇게되면 this는 무조건 전역 객체를 가르키는데, 애초에 저게 클래스 안인지라 strict mode가 적용되어 undefined가 바인딩이 되어버려 에러가 나온것이다. 오른쪽 코드는 화살표 함수로 대체한것이고, 정상적으로 동작하는 것은 필자가 확인하였다. 화살표 함수는 함수 자체에 this 바인딩을 갖지 않고, 따라서 상위 스코프의 this를 그대로 참조한다. 이것을 lexical this라고도 부르고, 우리가 알고 있는 렉시컬 스코프와 같이 화살표함수가 정의된 위체 의해 결정된다는 것을 의미합니다.

 

화살표 함수말고 이런 콜백 함수 내부 this 문제는 어떻게 해결해 왔을까 ? 

 

1. prefixer를 가르키는 this를 회피시킨뒤 , 콜백 함수 내부에서 사용한다.

2. map의 두번째 인수로 콜백 함수 내부 this로 사용할 객체를 전달할 수 있다. 

3. bind 메소드를 사용해 prefixer를 가르키는 this를 바인딩한다. 

 


Rest 파라미터 

함수에 전달된 인순들의 목록을 배열로 전달받는 건데, 매개변수 이름앞에 ...을 붙여서  정의한 매겨변수를 의미 

 

1. Rest 파라미터는 함수 정의시 선언한 매개변수 개수를 나타내는 함수 객체의 length에 영향을 끼치지 않는다. 

2. 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있어서 배열 메소드를 사용할 수 있다. 

3. 매개변수 기본 값을 통해 방어코드를 따로 작성안해도 된다.