[책정리] CoreJavaScript 3-2-5,6

이진규·2022년 8월 5일
1
post-thumbnail

3-2-5 화살표 함수의 예외사항

Q. 화살표 함수가 뭔가요?

 화살표 함수란 ES6에 새롭게 도입된 함수 표현 방식입니다. 화살표 함수를 사용하는 이유는 두 가지를 꼽을 수 있는데

  1. 코드 간소화
// 원소이름을 요소로 갖고있는 배열입니다.
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줄까지 줄여서 코드를 간소화할 수 있습니다.

  1. 바인딩 하지 않은 this
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: "의 이후 출력값이 같습니다.

Q. 그래서 뭐가 예외사항이에요?

 위에서 얘기했듯이 화살표함수는 자신의 this가 없고 가장 가까운 곳의 this를 사용하는 성질 때문에 명시적으로 this를 바인딩 할 필요 없이, 별도의 변수로 this를 우회하거나 call/apply/bind를 적용할 필요가 없어서 예외사항입니다.


3-2-6 별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)

Q. 콜백함수가 뭐에요?

 콜백함수는 다음 장에서 자세히 다룰건데, 여기서 얘기하는 이유는 콜백 함수를 인자로 받는 메소드 중 일부가 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의 내용정리입니다. 긴 글 읽어주셔서 감사합니다.

참고

  • MDN 화살표함수
  • 정재남, ⌜코어 자바스크립트⌟, 위키북스, 2022, 90 - 93쪽
profile
개발자

0개의 댓글