JS Higher Order Function
Table of contents
.reduce()
Array.prototype.reduce<U>(callback: (state: U, element: T, index: number, array: T[]) => U, firstState?: U): U
- ์๋ณธ ๋ฐฐ์ด์ ์์ ํ์ง ์๋๋ค.
- ์ด์ ์ ์ฝ๋ฐฑํจ์ ์คํ ๋ฐํ๊ฐ์ ์ ๋ฌ ํ์ฌ ์ฝ๋ฐฑํจ์๋ฅผ ์คํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
- ๋๋ฒ์งธ ์ธ์๋ก ์ด๊ธฐ๊ฐ์ ์ ๋ฌํ ์ ์๋ค.
- ์ฝ๋ฐฑ ํจ์์ ์ต์ด๋ก ์ ๋ฌ๋๋ค.
- ๊ฐ์ฒด์ ํ๋กํผํฐ ๊ฐ์ ํฉ์ฐํ๋ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ ์ด๊ธฐ๊ฐ์ ์ ๋ฌํด์ผ ํ๋ค.
- ๋น ๋ฐฐ์ด์ ํธ์ถํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
- ์ด๊ธฐ๊ฐ์ ์ ๋ฌํ๋ฉด ์๋ฌ๋ฅผ ํํผํ ์ ์๋ค.
- ์ธ์ ๋ ์ด๊ธฐ๊ฐ์ ์ ๋ฌํ๋ ๊ฒ์ด ๋ณด๋ค ์์ ํ๋ค.
reduce ์์ฉ
ํ๊ท ๊ตฌํ๊ธฐ(getMean)
๋ฐฐ์ด์ ์ํํ๋ฉด์ accumulator
์ value
๋ฅผ ๋ํด์ sum
์ ๋ง๋ค๊ณ , ๋ง์ง๋ง์ ๋ฐฐ์ด์ ํฌ๊ธฐ๋ก ๋๋๋ ๋ก์ง
const data = [1, 2, 3, 4, 5, 6, 1];const reducer = (accumulator, value, index, array) => {if (index === array.length - 1) (accumulator + value) / array.length;return accumulator + value;};const getMean = data.reduce(reducer, 0);console.log(getMean); // 3.142857142857143
์ด๊ธฐ๊ฐ์ 0
์ผ๋ก ์ค์ ํ์ง ์์๋ ์ฒซ ๋ฒ์งธ ์ธ์์ธ data[0]
๊ฐ accumulator
๋ก ๋์ด๊ฐ๋ค.
ํ์ง๋ง ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ ๊ฒ์ด ๋ ์์ ํ๋ค.
ํํํ(flatten)
const data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];const flatArrayReducer = (accumulator, value, index, array) => {return [...accumulator, ...value];};const flattenedData = data.reduce(flatArrayReducer, []);console.log(flattenedData); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
ํํํ ๋งตํ(flattenMap)
๋ฐฐ์ด์ ์ํํ๋ฉด์ ๋ฐฐ์ด์ ๊ฐ์ผ๋ก ๋ค์ด์๋ object ์ key ์กด์ฌ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ,
unique ํ โcast ๋ฅผ key ๋ก ๊ฐ๋ ๋ฐฐ์ด์ ๊ฐ๋คโ์ ์ต์ข
์ ์ผ๋ก return ํ๋ ๋ก์ง
const input = [{"title": "์ํผ๋งจ","year": "2005","cast": ["์ฅ๋๊ฑด", "๊ถ์์ฐ", "์ด๋์ฑ", "์ฐจ์น์"]},{"title": "์คํ์์ฆ","year": "2013","cast": ["์ฐจ์น์", "์ ํด๊ท ", "์ฅ๋๊ฑด", "๊น์ํ"]},{"title": "๊ณ ์ง๋ผ","year": "1997","cast": []}];const flatMapReducer = (accumulator, value, index, array) => {const key = "cast";if (value.hasOwnProperty(key) && Array.isArray(value[key])) {value[key].forEach(val => {if (accumulator.indexOf(val) === -1) {accumulator.push(val);}});}return accumulator;};const flattenCastArray = input.reduce(flatMapReducer, []);console.log(flattenCastArray); // ['์ฅ๋๊ฑด', '๊ถ์์ฐ', '์ด๋์ฑ', '์ฐจ์น์', '์ ํด๊ท ', '๊น์ํ']
reduce๋ฅผ map ์ฒ๋ผ ์ฌ์ฉ
const arr = [1, 2, 3];const mapReducer = (acc, value) => {acc.push(value * 2);return acc;};const result = arr.reduce(mapReducer, []);const result2 = arr.reduce((acc, value) => {acc.push(value * 2)return acc;}, []);const result3 = arr.reduce((acc, value) => [...acc, value * 2], []);
reduce๋ฅผ filter ์ฒ๋ผ ์ฌ์ฉ
var arr = [4, 15, 377, 395, 400, 1024, 3000]var arr2 = arr.reduce((pre, value) => {if (value % 5 == 0) {pre.push(value);}return pre;}, []);
reduce์ ๋ค๋ฅธ ๊ณ ์ฐจํจ์ ๋น๊ต
reduce vs. map
const data = [1, 2, 3];const initialValue = [];const reducer = (accumulator, value) => {accumulator.push(value * 2);return accumulator;};const result = data.reduce(reducer, initialValue);console.log(result); // [2, 4, 6]const result2 = data.map(x => x * 2);console.log(result2); // [2, 4, 6]
map์ด ๋ ๊ฐ๋ ์ฑ์ด ์ข๋ค.
reduce vs. filter
const data = [1, 2, 3, 4, 5, 6];const initialValue = [];const reducer = (accumulator, value) => {if (value % 2 != 0) {accumulator.push(value);}return accumulator;};const result1 = data.reduce(reducer, initialValue);console.log(result1); // [1, 3, 5]const result2 = data.filter(x => x % 2 != 0);console.log(result2); // [1, 3, 5]
filter๊ฐ ๋ ๊ฐ๋ ์ฑ์ด ์ข๋ค.
reduce vs. filter+map
const data = [1, 2, 3, 4, 5, 6];const initialValue = [];const reducer = (accumulator, value) => {if (value % 2 != 0) {accumulator.push(value * 2);}return accumulator;}const result1 = data.reduce(reducer, initialValue);console.log(result1); // [2, 6, 10]const result2 = data.filter(x => x % 2 != 0).map(x => x * 2);console.log(result2); // [2, 6, 10]
filter/map์ ๋์์ ์ํํด์ผ ํ๋ค๋ฉด ๋ฐฐ์ด์ ๋ ๋ฒ ์ํํด์ผ ํ๋ค. ํ์ง๋ง reduce๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ฐฐ์ด์ ํ ๋ฒ๋ง ์ํํ๋ฉด ๋๋ค.
reducer๋ผ๋ ํจ์๋ก ๋ก์ง์ด ๋ถ๋ฆฌ๋์ด ์์ด ์ํ๋ฅผ ์ ๊ฒํด ๋น์ฉ์ด ์ ๊ฒ๋ ๋ค. ํ์ง๋ง filter/map์ ์ฌ์ฉํ๋ฉด ์ด๋ค ์์ ์ ์ํํ๋์ง ๋ ์ง๊ด์ ์ด๋ค.
- filter/map
- ๋ฐฐ์ด์ ๋ ๋ฒ ์ํ
- ์ด๋ค ์์ ์ ์ํํ๋์ง ๋ ์ง๊ด์
- reducer
- ๋ฐฐ์ด์ ํ ๋ฒ๋ง ์ํ
- ์ฌ์ฌ์ฉ์ฑ
.filter()
๋ฐฐ์ด์์ ํน์ ์ผ์ด์ค๋ง ํํฐ๋ง ์กฐ๊ฑด์ผ๋ก ์ถ์ถํ์ฌ ์๋ก์ด ๋ฐฐ์ด์ ๋ง๋ค๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค.
Array.prototype.filter(callback: (value: T, index: number, array: Array) => any, thisArg?: any): T[]
- ์๋ณธ ๋ฐฐ์ด์ ์์ ํ์ง ์๋๋ค.
- filter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด if ๋ฌธ์ ๋์ฒดํ ์ ์๋ค.
- ์ฝ๋ฐฑํจ์์ ์คํ ๊ฒฐ๊ณผ๊ฐ true์ธ ๋ฐฐ์ด ์์์ ๊ฐ๋ง์ ์ถ์ถํ ์๋ก์ด ๋ฐฐ์ด์ ๋ฐํํ๋ค.
.map()
map ๋ฉ์๋๋ ๋ฐฐ์ด์ ์ํํ๋ฉฐ ์์ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋งตํํ๊ธฐ ์ํ ํจ์์ด๋ค.
Array.prototype.map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]
์๋ณธ ๋ฐฐ์ด์ ์์ ํ์ง ์๋๋ค.
์ฝ๋ฐฑ ํจ์์ ๋ฐํ๊ฐ(๊ฒฐ๊ณผ๊ฐ)์ผ๋ก ์๋ก์ด ๋ฐฐ์ด์ ์์ฑํ์ฌ ๋ฐํํ๋ค.
๋๋ฒ์งธ ์ธ์๋ก this๋ฅผ ์ ๋ฌํ ์ ์๋ค.
- ๋ฐฐ์ด ์์์ ๊ฐ, ์์ ์ธ๋ฑ์ค, map ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ฐฐ์ด
- 2๋ฒ์งธ ์ธ์ this๋ฅผ ์ ๋ฌํ์ง ์์ผ๋ฉด this === window
- ES6์ Arrow function๋ฅผ ์ฌ์ฉํ๋ฉด this๋ฅผ ์๋ตํ์ฌ๋ ๋์ผํ ๋์์ ํ๋ค.
.forEach()
forEach ๋ฉ์๋๋ ๋ฐฐ์ด์ ์ํํ๋ฉฐ ์์ ๊ฐ์ ์ฐธ์กฐํ์ฌ ๋ฌด์ธ๊ฐ๋ฅผ ํ๊ธฐ ์ํ ํจ์์ด๋ค.
Array.prototype.forEach(callback: (value: T, index: number, array: T[]) => void, thisArg?: any): void
- ์๋ณธ ๋ฐฐ์ด์ ์์ ํ์ง ์๋๋ค.
- forEach ๋ฉ์๋๋ ์๋ณธ ๋ฐฐ์ด(this)์ ๋ณ๊ฒฝํ์ง ์๋๋ค.
- ๋ฐฐ์ด์ ์ํํ๋ฉฐ ๋ฐฐ์ด์ ๊ฐ ์์์ ๋ํ์ฌ ์ธ์๋ก ์ฃผ์ด์ง ์ฝ๋ฐฑํจ์๋ฅผ ์คํํ๋ค.
๋ฐํ๊ฐ์ undefined์ด๋ค. - ๋ฐฐ์ด์ ๋ชจ๋ ์์๋ฅผ ์ํํ๋ฉฐ ์ค๊ฐ์ ์ํ๋ฅผ ์ค๋จํ ์ ์๋ค.
- for ๋ฌธ์ ๋นํด ์ฑ๋ฅ์ด ์ข์ง๋ ์์ง๋ง for ๋ฌธ๋ณด๋ค ๊ฐ๋ ์ฑ์ด ์ข๋ค.
- ๋๋ฒ์งธ ์ธ์๋ก this๋ฅผ ์ ๋ฌํ ์ ์๋ค.
- ๋ฐฐ์ด ์์์ ๊ฐ, ์์ ์ธ๋ฑ์ค, filter ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ฐฐ์ด