여러 함수들
포스트
취소

여러 함수들

📍 고차 함수 ( higher order function )

함수를 인자로 받거나 함수를 결과로 반환하는 함수입니다.
JavaScript의 함수는 일급 객체이기 때문에 함수의 매개변수로 전달할 수 있으며, 리턴 값으로 사용할 수 있습니다.

1
2
3
4
5
const add = (x, y) => x + y;

const higherOrderFunction = (func, x, y) => func(x, y);

console.log(higherOrderFunction(add, 1, 2));

JavaScript에서는 배열 메서드를 이용해서 고차 함수를 사용합니다.
( Array.prototype.forEach(), Array.prototype.some(), Array.prototype.reduce() 등 )

1
2
3
4
const func = (v, i, self) => console.log(v, i, self);

// 함수를 인자로 받는 "Array.prototype.forEach()" ( 고차 함수 )
["a", "b", "c", "d"].forEach(func);

클로저도 고차 함수의 하나의 예시라고 볼 수 있는 것 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const outer = () => {
  // 자유 변수
  let _count = 0;

  // 클로저
  const inner = () => ++_count;

  return inner;
};

const myCount = outer();

console.log(myCount()); // 1
console.log(myCount()); // 2
console.log(myCount()); // 3
console.log(myCount()); // 4

console.log(myCount.count); // undefined

아래 예시는 고차 함수를 활용한 또 다른 예시입니다.
( 참고: « 자바스크립트 완벽 가이드 8장 248p » ( 데이비드 플래너건 지음, 한성용 옮김, 인사이트, 2022 ) )

1
2
3
4
5
6
7
8
9
10
11
12
const not = (func) => {
  return (...args) => {
    let result = func.apply(this, args);
    return !result;
  };
};

const isEven = (n) => n % 2 === 0;
const isOdd = not(isEven);

console.log(isEven(2)); // true
console.log(isOdd(2)); // false

📍 커링 함수 ( currying function )

코어 자바스크립트의 143p ~ 145p를 참고해서 예시를 만들었습니다.

여러 개의 인자를 받는 함수를 한번에 하나씩 인자로 받는 함수로 나눈 함수입니다.

1
2
3
const func = (x) => (y) => (z) => x + y + z;

console.log(func(1)(2)(3));

위 예시만 보면 활용법이 애매하다고 느껴질 수 있습니다.
여러 개의 매개변수를 받는 함수에 하나의 매개변수만 유동적이거나, 받을 인자를 라이브러리에서 제공하는 경우 유용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// https://jsonplaceholder.typicode.com/users/1
// https://jsonplaceholder.typicode.com/posts/1

const setUrl = (baseUrl) => (target) => (id) =>
    fetch(`${baseUrl}/${target}/${id}`);

// url과 target 고정 ( user 데이터 요청 )
const setTarget1 = setUrl("https://jsonplaceholder.typicode.com");
const setId1 = setTarget1("users");
// id 가변적
const fetchUser = setId1(Math.floor(Math.random() * 9) + 1);

fetchUser.then((res) => res.json()).then(console.log);

// url과 target 고정 ( post 데이터 요청 )
const setTarget2 = setUrl("https://jsonplaceholder.typicode.com");
const setId2 = setTarget2("posts");
// id 가변적
const fetchPost = setId2(Math.floor(Math.random() * 9) + 1);

fetchPost.then((res) => res.json()).then(console.log);

저희가 주로 사용하는 Reduxmiddleware에서도 커링 함수를 이용한다고 합니다.
아래와 같은 커링 함수를 middleware로 등록하면 dispatch를 통해 reducer에 가기 전에 logger를 거쳐서 정해진 동작을 수행하고 reducer로 이동하게 됩니다.
자세하게 설명하기엔 주제에 벗어나기 때문에 나중에 redux 포스팅을 하게되면 해당 포스트에서 설명하겠습니다.
그냥 “유명한 라이브러리에서도 커링 함수를 활용해서 기능을 구현한다”정도의 의미 전달을 위해 작성했습니다.

1
2
3
4
const logger = store => next => action => {
  console.log(store.getState());
  next(action);
}

📍 순수 함수 ( pure function )

side effect가 없고 같은 인자를 넣으면 항상 같은 값을 반환하는 함수를 의미합니다.
함수형 프로그래밍에서도 주로 사용하는 원칙정도로 알고 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let n1 = 10;
let n2 = 10;

// (1) 비순수 함수
const changeNumber = (number) => {
  n1 = number * 2;
};

// (2) 순수 함수
const getNumber = (number) => number * 2;

changeNumber(50);
n2 = getNumber(50);

console.log(n1); // 100
console.log(n2); // 100

위의 예시에서 결과적으로 둘 다 동일하게 변수를 변형시킵니다.
하지만 (1)에서는 함수 자체에서 외부 변수를 변화시키는 side effect가 발생했고, (2)는 그렇지 않습니다.

“이게 뭐가 중요한지 그냥 결과만 같으면 되는거 아닌가?”라고 생각할 수 있지만 코드가 길어지고 가독성과 유지·보수가 중요해지는 시점에서는 (1)(2)는 확연한 차이가 있습니다.

(1)의 경우에는 n1이라는 변수에 의존적이고 만약 (1)과 같이 n1에 의존적인 함수가 여러 개가 있다면 어떤 순서로 어떻게 n1이 변화하는지 파악하기가 정말 힘들어집니다.
반면 (2)의 경우에는 side effect가 없고 같은 인자에 항상 같은 값을 반환하기 때문에 주위 상황을 고려하지 않고 함수만으로 어떤 결과가 나오는지 추측하기 쉽습니다.

“모든 함수를 순수 함수로 만들겠다!”라는 것은 거의 불가능하지만 순수 함수로 만들 수 있다면 최대한 순수 함수로 만드는 방식을 지향하는 게 미래의 본인과 협업하는 다른 개발자들을 위한 좋은 방법이라고 생각합니다.
아마 이런식으로 순수 함수를 지향하는 코드를 작성하는 방식을 함수형 프로그래밍이라고 하는 것으로 알고 있습니다.

📍 콜백 함수 ( callback function )

다시 호출하는 함수라는 의미를 갖는 함수입니다.
대표적으로 특정 이벤트에 등록하는 함수, 비동기 처리 함수등이 있습니다.

1
2
3
4
5
6
7
8
9
10
11
// (1) 콜백 함수의 매개변수는 코드상으로는 알 수 없음
const callback = (e) => {
  console.log(e);
};

const $button = document.createElement("button");
$button.type = "button";

$button.addEventListener("click", callback);

$button.click();

(1)과 같은 함수를 콜백 함수라고 합니다.
즉, “click이라는 이벤트가 발생하면 내가 정의한 함수(위의 경우 callback())을 호출해줘”라는 의미를 갖습니다.

여기서 볼만한 것은 callback()의 매개변수입니다.
따지고 보면 저희가 addEventListener()의 함수 구현에 대해 볼 수 없기 때문에 어떤 인자를 넣어줄지 알 수 없는게 맞습니다.
하지만 제가 e를 사용한 이유는 명세서에 event객체가 매개변수로 들어오도록 구현했다고 했기 때문에 그것을 믿고 사용하는 것 뿐입니다.
엄밀히 말하면 매개변수도 그렇고 this도 알 수 없는게 맞습니다.

📍 팩토리 함수 ( factory function )

객체를 반환하는 함수를 의미합니다.
제가 사용해본 경험으로는 redux의 액션 크리에이터 함수입니다.

1
const createIncreaseCountAction = (number) => ({ type: "INCREASE", payload: number });

📮 레퍼런스

  1. « 코어 자바스크립트 5장 ( 143p ~ 145p ) » ( 정재남 지음, 위키북스, 2019 )
  2. « 자바스크립트 완벽 가이드 8장 ( 248p ) » ( 데이비드 플래너건 지음, 한성용 옮김, 인사이트, 2022 )
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.