[JS] Array 고차함수는 왜 생긴걸까?

Benza·2022년 2월 17일
0

🔎

목록 보기
3/11

c, java, ES6 이전의 JavaScript 같은 좀 연식이된(?) 언어로 학습하고 일을 했던 내게 Array 고차함수는 혼란시러웠다.
이 놈의 고차함수가 JS에는 왜 있는 것이고 어떻게 쓰이는지 알아보도록 하자!

forif가 있는데 왜 바꿔서 사용해?

대부분의 고차함수가 하는 일은 반복문, 조건문으로 구현이 가능한 기능들이다. 그럼에도 새롭게 고차함수를 만든이유는 무엇일까?

크게 두 가지로 나눌 수 있다.

  1. 가독성
  2. 오류 발생 원인 제거

알아보기 전에 먼저!

고차 함수는 JS에서 광범위하게 사용된다. 여러분은 심지어 고차 함수가 무엇인지 모를지라도, 이미 고차함수를 이용하여 프로그래밍 해왔을 것다.

고차 함수의 개념을 완전히 이해하기 위해서는 함수형 프로그래밍이 무엇인지 개념을 이해하는 것이 먼저다.

함수형 프로그래밍

함수형 프로그래밍은 함수를 다른 함수의 파라미터로 넘길 수도 있고 반환(return) 값으로 함수를 받을 수도 있는 프로그래밍 형태이다. 함수형 프로그래밍에서, 우리는 함수라는 용어 하에서(함수 단위로) 생각하고 코딩하게 된다.

함수형 프로그램은 순수 함수와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.

가독성 측면에서 장점

조건문이나 반복문은 코드 해석의 과정이 필요함으로 로직의 흐름을 한 눈에 이해하기 어렵게 하여 가독성을 해친다.

오류발생 원인 제거

변수는 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있다.

즉, 함수형 프로그래밍은 순수 함수를 통해 부수효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 일환이라고 할 수 있다.


배열 고차 함수

고차 함수는 함수를 인수로 전달받거나 함수를 반환하는 함수를 말한다.

JS의 함수는 일급 객체이므로 함수를 값처럼 인수로 전달할 수 있으며 반환할 수도 있다.

1️⃣ Array.prototype.sort(compareFn?: (a: T, b: T) => number)

배열의 요소를 적절하게 정렬한다. 원본 배열을 직접 변경하며 정렬된 배열을 반환한다.

Array.prototype.sort 메서드는 10개 이상의 요소가 있는 배열을 정렬할 때 불안정한 알고리즘인 quicksort 알고리즘을 사용했다. 배열이 올바르게 정렬되도록 ECMAScript 2019는 Array.prototype.sort 메서드에 Timsort 알고리즘을 사용한다.
자세한 내용은 2019년과 이후 JavaScript의 동향 - JavaScript(ECMAScript)를 참고하기 바란다.

const fruits = ['Banana', 'Orange', 'Apple'];

// ascending(오름차순)
fruits.sort();
console.log(fruits); // [ 'Apple', 'Banana', 'Orange' ]

// descending(내림차순)
fruits.reverse();
console.log(fruits); // [ 'Orange', 'Banana', 'Apple' ]

기본 정렬 순서는 문자열 Unicode 코드 포인트 순서에 따른다. 배열의 요소가 숫자 타입이라 할지라도 배열의 요소를 일시적으로 문자열로 변환한 후, 정렬한다.

예를 들어, 문자열 ‘1’의 Unicode 코드 포인트는 U+0031, 문자열 ‘2’의 Unicode 코드 포인트는 U+0032이다. 따라서 문자열 ‘1’의 Unicode 코드 포인트 순서가 문자열 ‘2’의 Unicode 코드 포인트 순서보다 앞서므로 문자열 ‘1’과 ‘2’를 sort 메소드로 정렬하면 1이 2보다 앞으로 정렬된다. 하지만 10의 Unicode 코드 포인트는 U+0031U+0030이므로 2와 10를 sort 메소드로 정렬하면 10이 2보다 앞으로 정렬된다.

이러한 경우, sort 메소드의 인자로 정렬 순서를 정의하는 비교 함수를 인수로 전달한다. 비교 함수를 생략하면 배열의 각 요소는 일시적으로 문자열로 변환되어 Unicode 코드 포인트 순서에 따라 정렬된다.

const points = [40, 100, 1, 5, 2, 25, 10];

// 숫자 배열 오름차순 정렬
// 비교 함수의 반환값이 0보다 작은 경우, a를 우선하여 정렬한다.
points.sort(function (a, b) { return a - b; });
// ES6 화살표 함수
// points.sort((a, b) => a - b);
console.log(points); // [ 1, 2, 5, 10, 25, 40, 100 ]

// 숫자 배열에서 최소값 취득
console.log(points[0]); // 1

// 숫자 배열 내림차순 정렬
// 비교 함수의 반환값이 0보다 큰 경우, b를 우선하여 정렬한다.
points.sort(function (a, b) { return b - a; });
// ES6 화살표 함수
// points.sort((a, b) => b - a);
console.log(points); // [ 100, 40, 25, 10, 5, 2, 1 ]

// 숫자 배열에서 최대값 취득
console.log(points[0]); // 100

2️⃣ Array.prototype.forEach(callback: (value: T, index: number, array: T[]) => void, thisArg?: any)

  • forEach 메소드는 for 문 대신 사용할 수 있다.
  • 배열을 순회하며 배열의 각 요소에 대하여 인자로 주어진 콜백함수를 실행한다. 반환값은 undefined이다.
  • 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, forEach 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • forEach 메소드는 원본 배열(this)을 변경하지 않는다. 하지만 콜백 함수는 원본 배열(this)을 변경할 수는 있다.
  • forEach 메소드는 for 문과는 달리 break 문을 사용할 수 없다. 다시 말해, 배열의 모든 요소를 순회하며 중간에 순회를 중단할 수 없다.
  • forEach 메소드는 for 문에 비해 성능이 좋지는 않다. 하지만 for 문보다 가독성이 좋으므로 적극 사용을 권장한다.
  • IE 9 이상에서 정상 동작한다.

참고자료

profile
Understanding the impression

0개의 댓글