정의
-
함수를 인자로 전달받거나 함수를 결과로 반환하는 함수를 말한다.
-
인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다.
-
자바스크립트 함수는 일급객체이므로 값처럼 인자로 전달할 수 있으며 반환할 수도 있다.
-
아래의 예시는 언어 내부에 포함된 (built-in) 고차함수이다.
Array.prototype.map();
Array.prototype.filter();
Array.prototype.reduce();
-
고차 함수는 외부 상태 변경이나 가변(mutable) 데이터를 피하고 **불변성(Immutability)**을 지향하는 함수형 프로그래밍에 기반을 두고 있다.
함수형 프로그래밍은 순수 함수(Pure function)와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.
조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 하여 가독성을 해치고, 변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있기 때문이다.
-
함수형 프로그래밍은 결국 순수 함수를 통해 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법이라고 할 수 있다.
Array의 고차함수들
Array.prototype.sort(compareFn?: (a: T, b: T) => number): this
- 배열의 요소를 적절하게 정렬한다. 원본 배열을 직접 변경하며 정렬된 배열을 반환한다.
const fruits = ['Banana', 'Orange', 'Apple'];
fruits.sort();
console.log(fruits);
fruits.reverse();
console.log(fruits);
const points = [40, 100, 1, 5, 2, 25, 10];
points.sort();
console.log(points);
const points = [40, 100, 1, 5, 2, 25, 10];
points.sort(function (a, b) {
return a - b;
});
console.log(points);
console.log(points[0]);
points.sort(function (a, b) {
return b - a;
});
console.log(points);
console.log(points[0]);
Array.prototype.forEach(callback: (value: T, index: number, array: T[]) => void, thisArg?: any): void
- forEach 메소드는 for 문 대신 사용할 수 있다.
- 배열을 순회하며 배열의 각 요소에 대하여 인자로 주어진 콜백함수를 실행한다. 반환값은 undefined이다.
- 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, forEach 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- forEach 메소드는 원본 배열(this)을 변경하지 않는다. 하지만 콜백 함수는 원본 배열(this)을 변경할 수는 있다.
- forEach 메소드는 for 문과는 달리 break 문을 사용할 수 없다. 다시 말해, 배열의 모든 요소를 순회하며 중간에 순회를 중단할 수 없다.
- forEach 메소드는 for 문에 비해 성능이 좋지는 않다. 하지만 for 문보다 가독성이 좋으므로 적극 사용을 권장한다.
- IE 9 이상에서 정상 동작한다.
const numbers = [1, 2, 3];
let pows = [];
for (let i = 0; i < numbers.length; i++) {
pows.push(numbers[i] ** 2);
}
console.log(pows);
pows = [];
numbers.forEach(function (item) {
pows.push(item ** 2);
});
console.log(pows);
const numbers = [1, 2, 3, 4];
numbers.forEach(function (item, index, self) {
self[index] = Math.pow(item, 2);
});
console.log(numbers);
[1, 2, 3].forEach(function (item, index, self) {
console.log(`self[${index}] = ${item}`);
if (item > 1) break;
});
- forEach 메소드에 두번째 인자로 this를 전달할 수 있다.
function Square() {
this.array = [];
}
Square.prototype.multiply = function (arr) {
arr.forEach(function (item) {
this.array.push(item * item);
}, this);
};
const square = new Square();
square.multiply([1, 2, 3]);
console.log(square.array);
Square.prototype.multiply = function (arr) {
arr.forEach((item) => this.array.push(item * item));
};
Array.prototype.map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]
- 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백 함수의 반환값(결과값)으로 새로운 배열을 생성하여 반환한다. 이때 원본 배열은 변경되지 않는다.
- forEach 메소드는 배열을 순회하며 요소 값을 참조하여 무언가를 하기 위한 함수이며 map 메소드는 배열을 순회하며 요소 값을 다른 값으로 맵핑하기 위한 함수이다.
- 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, map 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- IE 9 이상에서 정상 동작한다.
const numbers = [1, 4, 9];
const roots = numbers.map(function (item) {
return Math.sqrt(item);
});
console.log(roots);
console.log(numbers);
Array.prototype.filter(callback: (value: T, index: number, array: Array) => any, thisArg?: any): T[]
- filter 메소드를 사용하면 if 문을 대체할 수 있다.
- 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수의 실행 결과가 true인 배열 요소의 값만을 추출한 새로운 배열을 반환한다.
- 배열에서 특정 케이스만 필터링 조건으로 추출하여 새로운 배열을 만들고 싶을 때 사용한다. 이때 원본 배열은 변경되지 않는다.
- 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, filter 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- IE 9 이상에서 정상 동작한다.
const result = [1, 2, 3, 4, 5].filter(function (item, index, self) {
console.log(`[${index}] = ${item}`);
return item % 2;
});
console.log(result);
Array.prototype.reduce<U>(callback: (state: U, element: T, index: number, array: T[]) => U, firstState?: U): U
- 배열을 순회하며 각 요소에 대하여 이전의 콜백함수 실행 반환값을 전달하여 콜백함수를 실행하고 그 결과를 반환한다. IE 9 이상에서 정상 동작한다.
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduce(function (previousValue, currentValue, currentIndex, self) {
console.log(previousValue + '+' + currentValue + '=' + (previousValue + currentValue));
return previousValue + currentValue;
});
console.log(sum);
const max = arr.reduce(function (pre, cur) {
return pre > cur ? pre : cur;
});
console.log(max);
- Array.prototype.reduce의 두번째 인수로 초기값을 전달할 수 있다. 이 값은 콜백 함수에 최초로 전달된다.
- 초기값은 다양하게 가능하다!
const sum = [1, 2, 3, 4, 5].reduce(function (pre, cur) {
return pre + cur;
}, 5);
console.log(sum);
Array.prototype.some(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): boolean
- 배열 내 일부 요소가 콜백 함수의 테스트를 통과하는지 확인하여 그 결과를 boolean으로 반환한다.
- 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- IE 9 이상에서 정상 동작
let res = [2, 5, 8, 1, 4].some(function (item) {
return item > 10;
});
console.log(res);
res = [12, 5, 8, 1, 4].some(function (item) {
return item > 10;
});
console.log(res);
res = ['apple', 'banana', 'mango'].some(function (item) {
return item === 'banana';
});
console.log(res);
Array.prototype.every(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): boolean
- 배열 내 모든 요소가 콜백함수의 테스트를 통과하는지 확인하여 그 결과를 boolean으로 반환한다.
- 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- IE 9 이상에서 정상 동작
let res = [21, 15, 89, 1, 44].every(function (item) {
return item > 10;
});
console.log(res);
res = [21, 15, 89, 100, 44].every(function (item) {
return item > 10;
});
console.log(res);
Array.prototype.find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined
- ES6에서 새롭게 도입된 메소드로 Internet Explorer에서는 지원하지 않는다.
- 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환한다.
콜백함수의 실행 결과가 참인 요소가 존재하지 않는다면 undefined를 반환한다.
- 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
- 참고로 filter는 콜백함수의 실행 결과가 true인 배열 요소의 값만을 추출한 새로운 배열을 반환한다.
따라서 filter의 반환값은 언제나 배열이다.
하지만 find는 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환하므로 find의 결과값은 해당 요소값이다.
const users = [
{id: 1, name: 'Lee'},
{id: 2, name: 'Kim'},
{id: 2, name: 'Choi'},
{id: 3, name: 'Park'},
];
let result = users.find(function (item) {
return item.id === 2;
});
console.log(result);
result = users.filter(function (item) {
return item.id === 2;
});
console.log(result);
Array.prototype.findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number
- ES6에서 새롭게 도입된 메소드로 Internet Explorer에서는 지원하지 않는다.
- 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫번째 요소의 인덱스를 반환한다.
콜백함수의 실행 결과가 참인 요소가 존재하지 않는다면 -1을 반환한다.
- 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
const users = [
{id: 1, name: 'Lee'},
{id: 2, name: 'Kim'},
{id: 2, name: 'Choi'},
{id: 3, name: 'Park'},
];
function predicate(key, value) {
return function (item) {
return item[key] === value;
};
}
let index = users.findIndex(predicate('id', 2));
console.log(index);
index = users.findIndex(predicate('name', 'Park'));
console.log(index);
참고 자료
정의
함수를 인자로 전달받거나 함수를 결과로 반환하는 함수를 말한다.
인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다.
자바스크립트 함수는 일급객체이므로 값처럼 인자로 전달할 수 있으며 반환할 수도 있다.
아래의 예시는 언어 내부에 포함된 (built-in) 고차함수이다.
고차 함수는 외부 상태 변경이나 가변(mutable) 데이터를 피하고 **불변성(Immutability)**을 지향하는 함수형 프로그래밍에 기반을 두고 있다.
함수형 프로그래밍은 순수 함수(Pure function)와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.
조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 하여 가독성을 해치고, 변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있기 때문이다.
함수형 프로그래밍은 결국 순수 함수를 통해 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법이라고 할 수 있다.
Array의 고차함수들
Array.prototype.sort(compareFn?: (a: T, b: T) => number): thisArray.prototype.forEach(callback: (value: T, index: number, array: T[]) => void, thisArg?: any): voidArray.prototype.map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]Array.prototype.filter(callback: (value: T, index: number, array: Array) => any, thisArg?: any): T[]Array.prototype.reduce<U>(callback: (state: U, element: T, index: number, array: T[]) => U, firstState?: U): UArray.prototype.some(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): booleanArray.prototype.every(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): booleanArray.prototype.find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined콜백함수의 실행 결과가 참인 요소가 존재하지 않는다면 undefined를 반환한다.
따라서 filter의 반환값은 언제나 배열이다.
하지만 find는 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환하므로 find의 결과값은 해당 요소값이다.
Array.prototype.findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number콜백함수의 실행 결과가 참인 요소가 존재하지 않는다면 -1을 반환한다.
참고 자료