adder = (a, b) => a + b;
console.log(adder(2, 3));
>>> 5
JS로 작성된 코드들을 보면 위와 같이 () 와 화살표(=>) 를 이용한 표현들을 볼 수 있습니다. adder에 어떤 표현식을 대입할 수 있고 adder(2, 3) 를 호출하면 return a + b; 를 하는 함수처럼 동작합니다. 실제로 위 표현은 화살표 함수라고 해서 함수를 간결하게 쓸 수 있는 표현 방법입니다.
adder = (a, b) => a + b;
사실 이 표현은
adder = function(a, b) { return a + b };
이 표현과 같은 것입니다. 대충 function 키워드를 빼고 화살표를 추가한 거 같은데 return은 어디로 사라졌을까요?
오늘은 화살표 함수(Arrow Function) 에 알아봅시다.
함수 선언식 vs 함수 표현식
화살표 함수를 알기전에 JS에서 함수를 나타내는 2가지 방법을 보겠습니다.
함수 선언식
function adder(a, b){
return a+b;
}
일반적으로 프로그래밍 언어에서 선언하듯이 함수를 선언하는 방식입니다.
function 키워드를 이용해서 선언할 수 있으며, JS는 실행전 초기화 단계에서 코드의 모든 함수 선언식을 찾아서 생성을 해두는 호이스팅을 일으키기 때문에 코드 위치상 adder 함수 이전에 adder을 호출해도 정상적으로 작동합니다.
console.log(adder(1,2));
function adder(a, b){
return a+b;
}
본 코드를 실행시켜보면 문제 없이 실행이 됩니다. JS는 기본적으로 위에서 아래로 차례대로 코드를 읽지만 호이스팅에 의해 미리 함수가 생성되었기 때문에 (함수 선언식) 문제없이 호출이 되는 것입니다.
만약에 C언어에서 어떤 함수를 호출하는데 이전 코드에서 미리 선언이 되어있지 않으면 십중팔구 오류가 발생하겠죠. 그러나 JS에서 함수 선언식을 활용하면 호이스팅 되어서 최상위로 끌어올려지기 때문에 자유롭게 사용할 수 있는 장점이 생깁니다. 이럴땐 호이스팅이 장점같이 보이지만 var 같은건 오히려 혼란을 야기하기 때문에.. 저는 그렇게 바람직한 동작이라곤 생각되지 않네요.
함수 표현식
const adder = function (a, b){
return a+b;
}
함수 표현식은 JS의 유연한 특징을 보여주는 선언 방식입니다.
일반적으로 변수에 어떤 것을 대입할 수 있으면 그 값을 1급 시민(객체) 라고 부르고, 만약에 대입할 수 없다면 2급 시민이라고 합니다.
JS는 함수를 특별한 종류의 값(value) 으로 취급하기 때문에 함수를 다른 변수에 값으로써 할당할 수 있습니다.
JS에서 함수는 1급 객체입니다. If문 같은건 변수에 대입이 되나요? 불가능합니다. 그렇기 때문에 If문은 JS에서 2급 시민이 되는 것이죠.
변수의 이름 adder이 함수의 이름이 되며, 호출할 때 이름이기 때문에 대입하는 함수는 이름이 필요 없는 익명 함수를 대입시켜주면 됩니다.
저 위 표현은 아까 선언식에서 만들었던 adder 함수와 동일한 표현이며, 사용 방식, 동작 방식도 동일합니다.
그러나 한가지 차이점이 있는데 함수 표현식은 함수 선언식과 다르게 코드가 도달하면 생성하기 때문에 호이스팅의 영향을 받지 않습니다.
adder(2, 3); //Error
const adder = function (a, b){
return a+b;
}
아까전에 함수 선언식은 값이 잘 출력됐지만 함수 표현식은 오류가 납니다.
C언어나 일반적인 프로그래밍 언어에서 알던 순차적인 흐름이죠.
함수 선언식과 함수 표현식 중에 무엇을 써야 할까요? 사실 무엇을 쓰던지 상관 없습니다. 자유성이 필요하면 함수 선언식을, 코드의 엄격함이 필요하면 함수 표현식을 사용하시면 됩니다.
화살표 함수
방금전에 배운 함수 표현식을 조금더 간결하게 작성해봅시다. 화살표 함수를 이용하면 함수를 더 간단하게 작성할 수 있습니다. JS는 함수를 1급 객체로 취급하고 값으로 대입 가능하기 때문에 함수의 인자값으로 함수를 넘기고, 함수 내부에서 그 인자값으로 들어온 함수를 호출하는 콜백 함수(CallBack Function) 라는 개념을 코드 작성시에 자주 이용하는데, 그래서 함수를 작성해야 할 일이 많습니다.
특히 콜백 함수를 인자값으로 넘길때는 한번만 일회용으로 쓸것이라 함수 표현식에서 쓰던 익명 함수를 작성하는 경우가 많구요.
본인도 처음에는 이 화살표 함수로 작성된 코드를 읽으면서 도대체 이게 무슨뜻인지..? 참 난해했습니다. JS 코드에서 굉장히 많이 사용되므로 꼭 알아둡시다.
const adder = function (a, b){
return a+b;
}
아까전에 두 값을 인자로 받아서 합을 return 하는 함수 표현식으로 작성된 adder 함수를 가져와 보았습니다.
이를 화살표 함수로 축약해보겠습니다.
const adder = (a, b) => {
return a+b;
}
1. function 키워드를 제거하고 중괄호 이전에 화살표(=>) 를 추가합니다.
const adder = (a, b) => (
a+b;
)
2. 본 예제는 코드 구문이 한줄이고 return 문이 있기 때문에 위 처럼 바꿀 수 있습니다. return문은 중괄호( { , } )가 아닌 일반 괄호( (, ) )로 바꿀 수 있습니다.
const adder = (a, b) => a+b;
3. return문이 한줄이라면 괄호도 생략할 수 있습니다.
결과 : 코드가 간결해졌습니다!
화살표 함수가 뭔지 모르는 사람들이 보기엔 return이 생략되어 있다는걸 모르면 도대체 저게 함수인지, 함수인건 알겠는데 무슨 기능을 하는지 당최 무슨 말인지 모르겠지만
저게 화살표 함수고 return이 생략되어 있다는 것을 안다면, a와 b라는 인자를 받아서 a+b를 return 하는 함수구나 한눈에 들어오게 됩니다. (물론 알아야 들어오지 저도 처음에 봤을땐 정말 생소했습니다.. 글쓰는 지금까지도 사실 생소해요 ㅎㅎ)
또 앞에서 따로 말씀드리진 않았지만 화살표 함수는 익명 함수에서만 사용할 수 있기 때문에 함수 표현식을 예제로 가져온 것 입니다.
화살표 함수 연습
<1>
let ShowError = function () {
console.log("Error");
}
익숙해지기 위해 예제로 화살표 함수를 조금더 연습해보겠습니다.
let ShowError = () => {
console.log("Error");
}
1. function 을 날리고 화살표를 추가해줍니다.
참고 : (x) 와 같이 인자를 x 딱 하나만 받는다면 x 옆의 괄호를 생략할 수 있습니다만, 이렇게 인자값이 한개도 없으면 괄호를 생략할 수 없습니다. 위 코드에서 괄호 자체가 없어지면 이상한 코드가 되겠죠?
let ShowError = () => console.log("Error");
2. {, } 안의 코드가 한줄이기 때문에 생략이 가능합니다.
본 코드에선 별 문제가 없겠지만 아까도 봤듯이 const adder = (a, b) => a+b; 같은 코드는 암묵적으로 a+b가 return 되기 때문에 한 줄 짜리 코드에서 함수를 호출할 때 그 함수의 반환값이 중요하면 주의가 필요할 거 같습니다.
<2>
let two_time = function (x) {
return x * 2;
}
다음 코드를 생략해보겠습니다.
let two_time = (x) => {
return x * 2;
}
1. 역시 화살표 함수 형태로 변경해줍니다.
let two_time = (x) => x * 2;
2. 중괄호를 일반 괄호로 바꿔서 return을 대체합니다 (return을 없앱니다), 일반 괄호가 한줄이므로 날려버립니다.
* 자세한 과정은 위에 adder 참고
let two_times = x => x * 2;
3. 인자값이 x하나이므로 일반 괄호를 생략해줍니다.
결과 : 코드가 간결해졌습니다!
two_times라는 함수는 x라는 인자값을 받아서 2배를 해서 return 해주는 함수라는게 이제 어느정도 보이시겠죠? ㅎㅎㅎ
주의점
화살표 함수는 기존 함수를 완벽히 대체하는 문법이 아닙니다.
특히 대표적인 차이점이라면 기존에 function 으로 만드는 함수에서 잘 작동하는 this 키워드가 화살표 함수로 바꾸면 동작하지 않는 경우가 대부분입니다.
객체를 만들고 자신의 프로퍼티 name을 가리켜야 할 때 this.name 과 같은 형태로 사용할 것인데 만약에 화살표 함수 안에서 저 this 를 사용하면 동작하지 않습니다.
일반적으로 화살표 함수의 this는 언제나 상위 스코프의 this를 가리키는데, 이것을 Lexical this 라고 합니다. 사실 이렇게 깊게 들어가면 끝이 없기 때문에.. 본 글에선 화살표 함수의 문법만 다루도록 하겠습니다. 어쨌던 객체 안에서 this 를 사용할때는 화살표 함수는 사용하지 마시고, 또 일반 함수에서는 잘 작동하는 것이 화살표 함수에서 작동하지 않으면 일반 함수 키워드로 바꿔서 사용하시면 되겠습니다.
물론 특수한 상황이 아닌 이상 대부분 문제가 없을 것이니 문제가 생기면 그때 이유를 차근 차근 알아가시면 되겠습니다.
<참고>
https://www.youtube.com/watch?v=KF6t61yuPCY&t=4520s
https://ossam5.tistory.com/158
https://velog.io/@parksj3205/2019-08-30-1208-%EC%9E%91%EC%84%B1%EB%90%A8
'웹 > JS' 카테고리의 다른 글
웹 프로젝트 리팩토링 -> TS(타입 스크립트) 도입했습니다 (0) | 2022.08.21 |
---|---|
[JS] Promise란? (then, catch, ...) - 프로미스 쉽게 이해하기 (0) | 2022.07.11 |
[JS] 콜백 함수(Callback Function)란? [콜백 함수를 쓰는 함수 직접 만들어보기] (0) | 2022.07.05 |
[JS] var, let, const의 차이점 (0) | 2022.07.03 |
[Polyfill] beforescriptexecute, beforescriptexecute 이벤트의 폴리필 (0) | 2020.10.11 |