일급 객체는 다음과 같은 특징을 가진다.
- 런타임에 생성이 가능하다.
- 변수에 할당할 수 있다.
- 다른 함수의 전달인자로 전달될 수 있다.
- 함수의 리턴값으로 사용될 수 있다.
자바스크립트에서 위의 조건을 만족하는, 그러니까 일급객체의 대표적 예시는 함수가 있다. 함수는 변수에 할당할 수 있기 때문에 전달인자로 전달이 가능하고, 배열의 요소나 객체의 속성값이 될 수 있다.
고차함수는 전달인자로 함수를 받을 수 있고, 함수를 리턴할 수 있는 함수이다.
고차함수에서, 전달인자로 전달되는 함수를 '콜백함수'라고 한다.
콜백 함수를 전달받은 고차 함수는, 함수 내부에서 이 콜백 함수를 호출할 수 있고, 조건에 따라 콜백 함수의 실행 여부를 결정할 수도 있다. 아예 호출하지 않을 수도 있고, 여러 번 실행할 수도 있다. 특정 작업의 완료 후에 호출하는 경우는 이후에 충분히 접할 수 있다.
또한 함수를 리턴하는 함수는 '커링함수'라고 부르기도 한다.
다른 함수를 인자로 받는 경우
function double(num) { return num * 2; } function doubleNum(func, num) { return func(num); } let output = doubleNum(double, 4); console.log(output); // -> 8
함수를 리턴하는 경우
function adder(added) { return function (num) { return num + added; }; } let output = adder(5)(3); // -> 8 console.log(output); // -> 8 const add3 = adder(3); output = add3(2); console.log(output); // -> 5
함수를 인자로 받고, 함수를 리턴하는 경우
function double(num) { return num * 2; } function doubleAdder(added, func) { const doubled = func(added); return function (num) { return num + doubled; }; } doubleAdder(5, double)(3); // -> 13 const addTwice3 = doubleAdder(3, double); addTwice3(2); // --> 8
JavaScript에는 기본적으로 내장된 고차 함수가 여럿 있다. 배열 메서드들 중 일부가 대표적인 고차 함수에 해당한다.
arr.filter(callback(element[, index[, array]])[, thisArg])
filter 메서드는 배열의 요소 중에서 특정 조건을 만족하는 요소들로 새 배열을 만든다. 즉, 조건에 true인 값들만으로 배열을 만든다.
const num = [1, 2, 3, 4, 5]
const even = num.filter((el) => {
return el % 2 === 0
})
console.log(even) // [2, 4]
arr.map(callback(currentValue[, index[, array]])[, thisArg])
모든 요소에 동일한 함수를 적용하고 반환한다.
const array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x * 2);
console.log(map1); [2, 8, 18, 32]
arr.reduce(callback[, initialValue])
배열의 요소에 함수를 적용하고 하나의 값으로 만든다.
초기값: 콜백함수에서 첫 인수에 제공할 값. 따로 설정하지 않는다면 배열의 0번째 인덱스가 자동으로 초기값이 된다.
const array1 = [1, 2, 3, 4];
const initialValue = 0;
const sumWithInitial = array1.reduce(
(previousValue, currentValue) => previousValue + currentValue,
initialValue
);
console.log(sumWithInitial);
arr.forEach(callback(currentvalue[, index[, array]])[, thisArg])
콜백함수를 배열의 요소 각각에 실행시켜주는 메서드이다. map과 달리, return이 없다.
const array1 = [1, 2, 3, 4];
myArr.forEach((currentElement, index, array) => {
console.log(`요소: ${currentElement}`);
console.log(`index: ${index}`);
console.log(array);
});
return값이 없기 때문에 변수에 할당하지 않고 그냥 바로 호출되는 것이 일반적이다. 만약 중간에 배열의 요소가 비어있다면 이는 그냥 건너 뛴다.
arr.find(callback[, thisArg])
주어진 판별 함수를 만족하는 첫 번째 요소의 값을 반환한다. 그런 요소가 없다면 undefined를 반환한다.
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10); // 10을 넘는 요소 중 첫 번째 요소는?
console.log(found); // 12
arr.sort([compareFunction])
콜백함수로는 배열의 요소들을 비교하는 함수가 들어온다. 만약 함수가 생략되면 각 문자의 유니코드 포인트 값에 따라 정렬된다.
함수가 생략되지 않았다면, 요소들은 콜백 함수의 리턴값에 따라 정렬된다. a,b를 비교한다면
compareFunction(a, b)이 0보다 작은 경우 a를 b보다 낮은 색인으로 정렬한다. 즉, a가 먼저온다.
compareFunction(a, b)이 0을 반환하면 a와 b를 서로에 대해 변경하지 않고 모든 다른 요소에 대해 정렬한다.
compareFunction(a, b)이 0보다 큰 경우, b를 a보다 낮은 인덱스로 소트합니다.
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers); // [1, 2, 3, 4, 5]
arr.some(function(currentValue, index, array), thisValue))
배열 안의 요소 중 단 한 요소만 함수의 조건을 통과해도 true를 반환한다.
const array = [1, 2, 3, 4, 5];
const even = (element) => element % 2 === 0; // 배열의 요소 중 짝수가 있는지?
console.log(array.some(even)); // true
arr.every(function(currentValue, index, array), thisValue))
배열의 모든 요소가 함수의 조건에 대해서 전부 true 인지를 판별해 Boolean 값을 반환한다.
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13]; // 배열의 모든 요소가 40 미만인지?
console.log(array1.every(isBelowThreshold)); // true
복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는 것
우리의 세상은 추상화로 가득 차 있다. '-1'을 표현하는 현실의 방법은 존재하지 않는다. 그러나 우리는 '-1'이라는 문자를 보고, -1은 0보다 1만큼 작은 수라고 설명할 수 있다. -1은 표현할 수 없는데도! 이렇듯, 인간은 추상화를 통해 생각하고 표현한다. 추상화를 이용하면, 효율적이고 편하게 생각할 수 있기 때문이다.
자바스크립트를 비롯한 많은 프로그래밍 언어 역시, 추상화의 결과이다. 컴퓨터를 구성하는 장치(중앙처리장치, CPU; Central Processing Unit)는 0과 1만 이해하는, 크롬 개발자 도구의 콘솔(console) 탭에서 다음의 코드를 입력하면 우리는 어떤 과정을 거쳐 10이 출력되는지 몰라도 10을 출력할 수 있다. 그런 복잡한 것들은 크롬의 자바스크립트 해석기(엔진)가 대신해 주기 때문이다.
즉, 추상화는 '생산성의 향상'이라고 볼 수 있다.
프로그램을 작성할 때, 자주 반복해서 사용하는 로직은 별도의 함수로 작성하기도 한다. 이 역시 추상화의 좋은 사례이다. 추상화의 관점에서 함수를 바라보면, 함수는 사고(thought) 또는 논리(logic)의 묶음이다. 함수를 통해 얻은 추상화를, 한 단계 더 높인 것이 고차 함수이다.
함수 = 값을 전달받아 값을 리턴한다 = 값에 대한 복잡한 로직은 감추어져 있다 = 값 수준에서의 추상화
고차 함수는 이 추상화의 수준을 사고의 추상화 수준으로 끌어올린다.
값 수준의 추상화: 단순히 값(value)을 전달받아 처리하는 수준
사고의 추상화: 함수(사고의 묶음)를 전달받아 처리하는 수준
고차 함수 = 함수를 전달받거나 함수를 리턴한다 = 사고(함수)에 대한 복잡한 로직은 감추어져 있다 = 사고 수준에서의 추상화