자바스크립트에도 특별한 대우를 받는 일급 객체(first-class citizen)가 있습니다. 대표적인 일급 객체 중 하나가 함수입니다. (자바스크립트가 나온 시점을 고려했을 때,) 자바스크립트에서 함수는 아래와 같이 특별하게 취급됩니다.
함수를 변수에 할당할 수 있기 때문에, 함수를 배열의 요소나 객체의 속성값으로 저장할 수 있습니다. 이는 함수를 데이터(string
, number
, boolean
, array
, object
)를 다루듯이 다룰 수 있다는 걸 의미합니다.
고차 함수(higher order function)는 함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수입니다
이때 다른 함수(caller)의 인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 합니다.
function double(num) { return num * 2; } function doubleNum(func, num) { return func(num); } /* * 함수 doubleNum은 다른 함수를 인자로 받는 고차 함수입니다. * 함수 doubleNum의 첫 번째 인자 func에 함수가 들어올 경우 * 함수 func는 함수 doubleNum의 콜백 함수입니다. * 아래와 같은 경우, 함수 double은 함수 doubleNum의 콜백 함수입니다. */ let output = doubleNum(double, 4); console.log(output); // -> 8
function adder(added) { return function (num) { return num + added; }; } /* * 함수 adder는 다른 함수를 리턴하는 고차 함수입니다. * adder는 인자 한 개를 입력받아서 함수(익명 함수)를 리턴합니다. * 리턴되는 익명 함수는 인자 한 개를 받아서 added와 더한 값을 리턴합니다. */ // adder(5)는 함수이므로 함수 호출 연산자 '()'를 사용할 수 있습니다. let output = adder(5)(3); // -> 8 console.log(output); // -> 8 // adder가 리턴하는 함수를 변수에 저장할 수 있습니다. // javascript에서 함수는 일급 객체이기 때문입니다. 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는 고차 함수입니다. * 함수 doubleAdder의 인자 func는 함수 doubleAdder의 콜백 함수입니다. * 함수 double은 함수 doubleAdder의 콜백으로 전달되었습니다. */ // doubleAdder(5, double)는 함수이므로 함수 호출 기호 '()'를 사용할 수 있습니다. doubleAdder(5, double)(3); // -> 13 // doubleAdder가 리턴하는 함수를 변수에 저장할 수 있습니다. (일급 객체) const addTwice3 = doubleAdder(3, double); addTwice3(2); // --> 8
map 함수는 모든 요소에게 동일한 행동을 주는 값에대하여 모두 반환하고 callbackFunction 을 실행한 결과를 가지고서 새로운 배열을 만들 때도 사용 합니다.
구문
array.map(callbackFunction(currentValute,index,array), thisArg
map 함수에는 callbackFunction
, thisArg
두 개의 매개변수가 있고
callbackFunction
은 currentValue
, index
, array
3개의 매개변수를 갖습니다.
currentValue
: 배열 내 현재 값
index
: 배열 내 현재 값의 인덱스
array
: 현재 배열.
thisArg
: callbackFunction
내에서 this
로 사용될 값
let numbers = [1,2,3,4,5]; let result = numbers.map(double => double * 2); console.log(result); // [2, 4, 6, 8, 10]
let animals = ['cat','lion','tiger','snake','dog']; let result = animals.map(animal => animal.length); console.log(result); // [3, 4, 5, 5, 3]
let numbers = [1,4,9,16,25,36]; let result = numbers.map(Math.sqrt); console.log(result); // [1, 2, 3, 4, 5, 6]
filter 함수는 callbackFunction의 조건에 해당하는 모든 요소가 있는 배열을 새로운 배열로 반환 합니다.
구문
array.filter(callbackFunction(element, index, array), thisArg);
filter 함수에는 callbackFunction
, thisArg
두 개의 매개변수가 있고
callbackFunction
은 element
, index
, array
3개의 매개변수를 갖습니다.
element
: 요소값
index
: 요소의 인덱스
array
: 사용되는 배열 객체
thisArg
: callbackFunction 내에서 this로 사용될 값
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']; const result = words.filter(word => word.length => 6); // ["exuberant", "destruction", "present"]
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']; const result = words.filter(word => word === 'limit'); // ["limit"]
reduce 함수는 배열을 하나의 값으로 만들어 줍니다.
또한 reduce는 초기값을 정할 수 있는대 정하지 않는다면 첫 번째 요소가 초기값이 됩니다
구문
array.reduce(function callbackFn(accumulator, currentValue, index, array){...}, initialValue)
reduce함수에는 callbackfunction
과 initialValue
2개의 매개변수가 있고
callbackFunction
은 accumulator
, currentValue
, currentIndex
, array
4개의 매개변수를 선택적으로 받을 수 있습니다.
accumulator
는 배열의 첫번째 인자, 혹은 initialValue
가 있을경우 initialValue
.
currentValue
는 배열 내 현재 처리되고 있는 값.
currentIndex
는 배열 내 현재 처리되는 있는 값의 인덱스.
array
는 현재 호출된 배열 입니다.
그리고 initialValue
은 최초 호출에서 첫 번째 인수에 제공하는 값. 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생합니다.
const arr = [1, 2, 3, 4, 5]; let result = arr.reduce((acc, cur, idx) => { return acc + cur } ); console.log(result) // 15
function joinName(resultStr, user) { resultStr = resultStr + user.name + ', '; return resultStr; } let users = [ { name: 'Tim', age: 40 }, { name: 'Satya', age: 30 }, { name: 'Sundar', age: 50 } ]; users.reduce(joinName, ''); // "Tim, Satya, Sundar, "
function makeAddressBook(addressBook, user) { let firstLetter = user.name[0]; if(firstLetter in addressBook) { addressBook[firstLetter].push(user); } else { addressBook[firstLetter] = []; addressBook[firstLetter].push(user); } return addressBook; } let users = [ { name: 'Tim', age: 40 }, { name: 'Satya', age: 30 }, { name: 'Sundar', age: 50 } ]; users.reduce(makeAddressBook, {});
리턴값
{ T: [ { name: 'Tim', age: 40 } ], S: [ { name: 'Satya', age: 30 }, { name: 'Sundar', age: 50 } ] }