[learning javascript] chapter 13. 함수와 추상적 사고

함수와 추상적 사고

서브루틴으로서의 함수

값을 반환하는 서브루틴으로서의 함수

함수로서의 함수

그래서?

함수도 객체다

IIFE와 비동기적 코드

변수로서의 함수

// 별명 쓰기 전 const answer = (addThreeSquareAddFiveTakeSquareRoot(5) + addThreeSquareAddFiveTakeSquareRoot(2)) / addThreeSquareAddFiveTakeSquareRoot(7);

// 별명 사용 const f = addThreeSquareAddFiveTakeSquareRoot; const answer = (f(5) + f(2)) / f(7);

- 별명 붙일 때 `addThreeSquareAddFiveTakeSquareRoot`뒤에 괄호를 붙이지 않았음
- 괄호를 붙이면 함수를 호출하고, f에 함수 결과가 저장됨

```javascript
const Money = require('math-money');    // require는 라이브러리를 불러오는 노드 함수
const oneDollar = Money.Dollar(1);

// Money.Dollar도 길게 느껴지면
const Dollar = Money.Dollar;
const twoDollars = Dollar(2);
// Dollar와 twoDollars는 같은 타입의 인스턴스

배열 안의 함수

const pipeline = [ function rotate(p) { return { x: p.x * cos(theta) - p.y * sin(theta), y: p.x * sin(theta) - p.y * cos(theta), }; }, function scale(p) { return { x: p.x * zoom, y: p.y * zoom }; }, function translate(p) { return { x: p.x + offset[0], y: p.y + offset[1]; }; }, ];

// pipeline은 2D변형에 필요한 함수의 배열 // 점 하나를 변형해 보면 const p = { x: 1, y: 1 }; let p2 = p; for(let i=0; i<pipeline.length; i++) { p2 = pipeline[i][p2]; }

// p2는 이제 P1을 좌표 원점 기준으로 45도 회전하고 // 원점에서 2 단위만큼 떨어뜨린 후 // 1단위 오른쪽, 3단위 아래쪽으로 움직인 점입니다.

- 파이프라인의 각 함수를 호출할 때 사용한 문법을 보면 pipeline[i]는 파이프라인의 i번째 요소에 접근하고, 그 요소는 함수로 평가
- 각 함수에 점을 전달하고, 반환값을 다시 그 점에 할당

#### 함수에 함수 전달

- 함수에 함수를 전달하는 다른 용도는 비동기적 프로그래밍
- 이런 용도로 전달하는 함수를 보통 콜백이라 부르며 약자로 cb라 씀
- 콜백 함수는 자신을 감싼 함수가 실행을 마쳤을 때 호출됨
- 함수는 동작이고, 함수를 받은 함수는 그 동작을 활용할 수 있음
```javascript
function sum(arr, f) {
    // 함수가 전달되지 않았으면 매개변수를 그대로 반환하는 null 함수를 씀
    if(typeof f != 'function') f = x => x;

    return arr.reduce((a, x) => a += f(x), 0);
}
sum([1, 2, 3]);                         // (6)
sum([1, 2, 3], x => x*x);               // 제곱을 합해서 반환하는 함수 (14)
sum([1, 2, 3], x => Math.pow(x, 3));    // 세제곱을 합해서 반환하는 함수 (36)

함수를 반환하는 함수

재귀

findNeedle([‘hay’, ‘hay’, ‘hay’, ‘hay’, ‘needle’, ‘hay’, ‘hay’]);

- 이 함수는 모든 가능성을 전부 고려
- 경우의 수는 haystack이 비어있거나, 배열의 첫 번째 요소가 바늘이거나, 바늘이 아닌 경우
- 마지막은 배열의 어딘가에 바늘이 들어있을 테니 `Array.prototype.shift`로 배열의 첫 번째 요소를 제거하고 함수를 반복
- 재귀 함수에는 종료 조건이 있어야 함
- `findNeedle`에는 두가지 종료 조건이 있음
    - 바늘을 찾거나
    - 배열이 비어 있거나
- 호출할 때마다 배열의 길이가 줄어들므로 언젠가는 두 조건 중 하나를 만족하게 됨
- 숫자의 계승(factorial)을 찾는 예제
```javascript
function fact(n) {
    if(n === 1) return 1;
    return n * fact(n-1);
}