나는 그동안 작지만 소중한 프로젝트들을 진행하면서 Arrow function
즉 화살표 함수를 그냥 단지 일반 function의 축약형이라 생각하고 써왔다
그런데 알고보니 매우 중요한 개념때문에 Arrow function이 ES6에 추가 되었더라고,,,?
그것도 모르고 짧다고 신나게 써댔던 나의 과거를 반성하며 글을 기록하려 한다,,,^^
ES6 문법 이후부터는 자바스크립트에서 함수를 만들 수 있는 문법이 새롭게 하나 등장했다
바로 arrow function 이라는 문법인데 이걸 이용하면 함수를 만들 수 있다.
근데 함수를 만드는 방법은 기존 function () {} 이게 있는데 왜 새로 추가했을까?
지금부터 그 이유를 알아보도록 하자!
(1)
function 일반함수(){
//어쩌구
}
(2)
let 일반함수 = function(){
//어쩌구
}
자바스크립트에선 함수를 (1) 또는 (2)처럼 만들고 일반함수(); 이렇게 함수를 사용한다.
근데 ES6 신문법을 사용하면 함수를 이렇게 만들 수도 있다.
let 일반함수 = () => {
//어쩌구
}
function이라는 길고 복잡한 키워드 대신에
=> 이런 직관적인 화살표를 사용해서 함수를 만들어내는 신문법이다.
그렇다면 과연 Arrow function은 단지 함수를 줄여서 사용하기 위해 나온 문법일까? ㄴㄴ 아님 그래서 블로그 쓰는중,,^^! 그럼 왜 나왔는지 용도들을 알아보자
프로그래밍을 할 때 우리는 왜 함수를 사용할까? 크게 두 가지로 나눠볼 수 있다.
- 여러가지 기능을 하는 코드를 한 단어로 묶고 싶을 때
(그리고 나중에 재사용할 때)- 입출력기능을 만들 때
이럴 때 함수를 사용해야 한다.
그리고 Arrow function을 사용하면 함수 본연의 입출력기능을 아주 직관적으로 잘 표현해준다! 엥 근데 입출력기능이 뭘까?
함수는 수학에서 온 개념이다.
원래 함수는 어떤 숫자를 집어넣으면 뭔가 다른 숫자를 배출하는 역할을 하는데 아래 그림처럼 input을 집어넣으면 output을 출력해주는 박스가 바로 함수다.
f(x) = x + 2 이다. 그럼 f(2)는 뭘까? 답은 4다.
f(x) 이게 함수다. 위와 같이 그림으로 표현하자면 아래와 같을 것이다.
그럼 프로그래밍에선 어떨까?
2를 집어넣으면 x + 2를 출력해주는 함수를 구현해보면 아래와 같이 나타낼 수 있다
function 더하기함수(x){
return x + 2
}
이런 문법을 이용해서 만들어 사용한다.
함수의 소괄호안에는 input역할을 하는 파라미터가 있고 함수내에 return이라는 것은 output역할을 하는 키워드이다.
그럼 이제 더하기함수(2); 이렇게 사용하시면 4가 이 자리에 남게 되는 것이다.
소괄호에 뭔가 집어넣으면 return을 이용해 뭔가 퉤 뱉어내는 것 이게 바로 함수의 입출력 기능이라고 할 수 있겠다.
다시 돌아와서arrow function을 쓰면 입출력기능이 아래와 같이 쉽고 직관적으로 표현된다.
let 곱하기함수 = (x) => { return x * 2 }
console.log( 곱하기함수(4) );
console.log( 곱하기함수(8) );
숫자를 넣으면 2배를 해주는 함수를 하나 만들었다.
함수 표현식 자체가 x가 x * 2가 된다라는 것을 쉽게 알아챌 수 있다.
이것이 바로 Arrow function의 첫번째 장점이다.
두번째 장점은 매우 간단하다.
파라미터가 하나라면 소괄호를 생략가능하다는 뜻이다. 아래 코드를 살펴보자
let 곱하기함수 = x => { return x * 2 }
console.log( 곱하기함수(4) );
console.log( 곱하기함수(8) );
이렇게 적어도 된다는 소리다. 끝이다
let 곱하기함수 = x => return x * 2
console.log( 곱하기함수(4) );
console.log( 곱하기함수(8) );
중괄호 안에 return 한줄 뿐이라면 중괄호와 return도 생략가능하다.
이렇게 소괄호와 중괄호가 생략되니 이제 x가 어떻게 변하는 함수인지 입출력기능이 바로 한눈에 들어온다!
arrow function을 쓰면 내부에서 this값을 쓸 때 밖에 있던 this값을 그대로 사용할 수 있는데 이게 바로 arrow function을 쓰는 핵심 이유이다.
(내가 이 글을 쓰는 이유이기도 하다)
함수를 쓸 때 함수가 쓰인 위치에 따라서 내부의 this값이 변한다.
근데 arrow function은 어디서 쓰든간에 내부의 this 값을 변화시키지 않는다.
바깥에 있던 this의 의미를 그대로 내부에서도 사용하는 함수가 바로 arrow function이라는 함수인 것이다! 예시를 살펴보자
let 오브젝트1 = {
함수 : function(){ console.log(this) }
}
오브젝트.함수()
위와 같은 코드를 실행시키면 콘솔창에 오브젝트인 오브젝트1이 뜰 것이다.
그럼 다시 아래 예제를 살펴보자
let 오브젝트1 = {
함수 : () => { console.log(this) }
}
오브젝트1.함수()
위의 코드는 실행하면 놀랍게도 window라는게 출력된다!
왜 함수의 주인인 오브젝트1이 출력되지 않냐면 this값은 함수를 만나면 항상 변하는데 arrow function 안에서는 변하지 않고 밖에 있던 this를 그대로 쓰기 때문이다. (오브젝트 밖에 있던 this는 window)
이게 왜 핵심 이유냐면 화살표 함수가 나오기 이전에 는 콜백 함수의 this와 외부함수의 this간 불일치 문제를 해결해야 했다.
쉽게 말하면 this 바인딩이 필요했다!
근데 이게 굉장히 귀찮다보니 문제가 되었었는데,
화살표 함수는 함수 자체의 this 바인딩을 갖지 않으며 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 참조하기 때문에 그동안 문제가 되었던 불일치 문제를 해결할 수 있게 된 것이다!!(핵심핵심 매우 중요)
정리하자면 콜백함수 내부의 this 문제를 화살표 함수를 사용하면 편하게 해결할 수 있다
아래의 예시를 살펴보자
let obj = {
myVar: 'foo',
myFunc: function() {
console.log(this.myVar)
setTimeout(function() {
console.log(this.myVar)
}, 1000)
}
}
obj.myFunc() // foo ... then... undefined
위와 같이 콜백함수는 undefined를 출력하고 있다.
콜백함수(setTimeout) 내부의 this는 전역 객체 window를 가리킨다.
하지만 myVar 프로퍼티는 window가 아니라 obj의 프로퍼티이기 때문에 오류가 발생한 것이다.
이를 해결하기 위해서는 this를 변수에 할당하는 하는 방법이나 bind,call,apply를 활용하여 this를 바인딩하는 방법이 있지만 가장 명확한 솔루션인 화살표 함수를 사용하면 아래와 같이 깔끔하게 해결이 가능하다!
let obj = {
myVar: 'foo',
myFunc: function() {
console.log(this.myVar)
setTimeout(() => {
console.log(this.myVar)
}, 1000)
}
}
obj.myFunc() // foo ... then... foo
이렇게 지금까지 화살표 함수가 무엇인지 부터 나오게 된 배경까지 알아보았다.
데이터 바인딩이 까다롭고 귀찮기 때문에 화살표 함수가 나오게 되었는데 이걸 알기 전 까지는 그냥 간단하고 짧아서 좋아라 썼었다
하지만 이제 정확하게 개념을 짚고나니 부끄러웠던 과거를 청산한 느낌,,(?)
앞으로는 내가 이걸 왜 쓰고 있는지 조금 더 근-본에 충실해야겠다는 생각이 들었다!