화살표 함수란 ES6에 새롭게 도입된 함수 표현 방식입니다. 화살표 함수를 사용하는 이유는 두 가지를 꼽을 수 있는데
// 원소이름을 요소로 갖고있는 배열입니다.
const elementList = [
'Hydrogen',
'Helium',
'Lithium',
'Berylium'
];
// 이 문장은 원소이름의 길이를 담은 배열을 반환합니다. [8, 6, 7, 9]
elementList.map(function(element){
return element.length;
});
// 위의 함수 표현을 아래 화살표 함수로 바꿔서 쓸 수 있습니다.
elementList.map((element) => {
return element.length;
});
// 파라매터가 하나만 있을 때 주변 괄호를 생략할 수 있습니다.
elementList.map(element => {
return element.length;
});
// 화살표 함수가 return만 할 때 return과 중괄호를 생략할 수 있습니다.
elementList.map(element => element.length);
위의 코드는 원소이름을 요소로 갖고있는 배열에서 원소이름의 길이를 담은 배열을 리턴하는 코드를 화살표 함수를 통해 줄이는 과정을 보여줍니다.
화살표 함수를 통해 같은 역할을 하는 3줄의 코드를 1줄까지 줄여서 코드를 간소화할 수 있습니다.
01 const obj = {
02 outer: function(){
03 console.log("outer:",this);
04 const innerNormal = function(){
05 console.log("normal this:",this);
06 }
07 const innerArrow = () => {
08 console.log("arrow this",this);
09 };
10 innerNormal();
11 innerArrow();
12 }
13 };
14 obj.outer();
15 // 실행 결과:
16 // outer: {outer: f ...}
17 // normal this: Window {...}
18 // arrow this: {outer: f ...}
위의 코드는 obj 객체의 outer 메소드 안에서 일반 함수를 실행할 때와 화살표 함수를 실행했을 때의 결과를 비교하는 코드입니다.
10 innerNormal();
10번째 줄에서 innerNormal()함수를 함수로서 호출하기때문에(함수앞에 '.'이 없으므로) 호출 주체를 명시하지 않았기 때문에 호출 주체의 정보를 알 수 없고 2장에서 이때 this는 전역 객체를 가리킨다고 했으므로
15 // 실행 결과:
17 // normal this: Window {...}
실행 결과에서의 this는 전역 객체인 Window를 가리키게 됩니다.
11 innerArrow();
11번째 줄에서 innerArrow()함수도 함수로서 호출되었지만, 화살표 함수이기에 자신의 this가 없고 가장 가까운 곳의 this를 사용하므로 obj객체의 this를 갖고와서 사용합니다.
15 // 실행 결과:
16 // outer: {outer: f ...}
18 // arrow this: {outer: f ...}
그래서 "outer: "와 "arrow this: "의 이후 출력값이 같습니다.
위에서 얘기했듯이 화살표함수는 자신의 this가 없고 가장 가까운 곳의 this를 사용하는 성질 때문에 명시적으로 this를 바인딩 할 필요 없이, 별도의 변수로 this를 우회하거나 call/apply/bind를 적용할 필요가 없어서 예외사항입니다.
콜백함수는 다음 장에서 자세히 다룰건데, 여기서 얘기하는 이유는 콜백 함수를 인자로 받는 메소드 중 일부가 this로 지정할 객체(thisArg)를 지정해서 인자로 넘겨줄 수 있기 때문입니다. thisArg를 넘겨줌으로써 콜백 함수 내부에서 넘겨받은 thisArg를 this로 사용할 수 있습니다.
이런 경우는 배열 메소드들에서 많이 발생합니다. forEach로 예시를 들어보겠습니다.
01 const report = {
02 sum: 0,
03 count: 0,
04 add: function(){
05 const args = Array.prototype.slice.call(arguments);
06 args.forEach(function(entry){
07 this.sum += entry;
08 ++this.count;
09 }, this);
10 },
11 average: function(){
12 return this.sum / this.count;
13 }
14 };
15 report.add(60, 85, 95);
16 console.log(report.sum, report.count, report.average());
17 // 결과: 240 3 80
위의 코드는 인자로 넘겨준 숫자들을 더해주는 add 메소드와 더해준 값들을 평균을 내는 average메소드를 갖고있는 report 객체를 만들고 60,85,95를 더하고 평균을 낸 결과를 출력합니다.
05 const args = Array.prototype.slice.call(arguments);
; 5번째 줄에서 add메소드의 인자로 전달받은 값들을 배열로 만들어서 args에 할당해주었고
06 args.forEach(function(entry){
07 this.sum += entry;
08 ++this.count;
09 }, this);
6~9번째 줄에서 args배열의 forEach문을 통해 배열을 돌면서 배열의 요소들을 더해서 sum에 저장해주고 배열의 개수에 맞춰서 count를 하나씩 더해줬습니다.
여기서 사용될 this를 지정해주기 위해 9번째 줄에서 forEach메소드의 두번째 인자로(첫번째 인자는 6~9번째 줄에 정의된 entry를 넘겨받는 익명함수입니다.) this를 넘겨주었습니다.
01 const report = {
02 sum: 0,
03 count: 0,
04 add: function(){
여기서 this는, 4번째 줄에서 시작되는 add메소드 내부에서의 this이므로 report 객체를 의미합니다.
06 args.forEach(function(entry){
07 this.sum += entry;
08 ++this.count;
09 }, this);
그래서 forEach함수 내부에서 this로 report객체에 접근할 수 있었습니다.
이처럼 별도의 인자로 this를 넘겨줌으로써 콜백 함수에서 넘겨받은 this를 this로 사용할 수 있게 되는데 이것이 별도의 인자로 this를 받는 경우입니다.
여기까지가 코어자바스크립트 3-2-5~3-2-6의 내용정리입니다. 긴 글 읽어주셔서 감사합니다.