TIL(20210707) - κ³ μ°¨ν¨μ
π Today
- μΌκΈ κ°μ²΄μ νΉμ§ νμ΅
- κ³ μ°¨ν¨μ κ°λ νμ΅
- λ΄μ₯ κ³ μ°¨ν¨μ(filter, map, reduce)νμ΅ λ°
λ΄μ₯ κ³ μ°¨ν¨μλ₯Ό μ¬μ©νμ¬ κ°λ¨ν μκ³ λ¦¬μ¦ λ¬Έμ νμ΄
π€ Learned
First-class citizen : μΌκΈκ°μ²΄ - νΉλ³ν λμ°λ₯Ό λ°λ ν¨μ
λΉνκΈ°μλ First classκ° μμ΅λλ€. μ΄μ½λ Έλ―Έ ν΄λμ€μλ νμΉμμλΆν° κΈ°λ΄μ, μνλ¬Όμ΄ λμ€λ μμκΉμ§ ν곡μ¬μ κ΄λ ¨λ λͺ¨λ λΆλΆμμ ννμ΄ λ€λ¦ λλ€. First class μ’μμ ꡬ맀ν μ¬λμ λΉμΌ κ°κ²©μ μΉλ₯΄κ³ , ν곡μ¬λ‘λΆν° νΉλ³ν λμ°λ₯Ό λ°μ΅λλ€.
μλ°μ€ν¬λ¦½νΈμλ νΉλ³ν λμ°λ₯Ό λ°λ μΌκΈ κ°μ²΄(first-class citizen)κ° μμ΅λλ€. λνμ μΈ μΌκΈ κ°μ²΄ μ€ νλκ° ν¨μμ λλ€. (μλ°μ€ν¬λ¦½νΈκ° λμ¨ μμ μ κ³ λ €νμ λ,) μλ°μ€ν¬λ¦½νΈμμ ν¨μλ μλμ κ°μ΄ νΉλ³νκ² μ·¨κΈλ©λλ€.
- λ³μμ ν λΉ(assignment) ν μ μλ€.
- λ€λ₯Έ ν¨μμ μΈμ(argument)λ‘ μ λ¬λ μ μλ€.
- λ€λ₯Έ ν¨μμ κ²°κ³Όλ‘μ 리ν΄λ μ μλ€.
ν¨μλ₯Ό λ³μμ ν λΉν μ μκΈ° λλ¬Έμ, ν¨μλ₯Ό λ°°μ΄μ μμλ κ°μ²΄μ μμ±κ°μΌλ‘ μ μ₯ν μ μμ΅λλ€. μ΄λ ν¨μλ₯Ό λ°μ΄ν°(string
, number
, boolean
, array
, object
)λ₯Ό λ€λ£¨λ―μ΄ λ€λ£° μ μλ€λ κ±Έ μλ―Έν©λλ€.
λ³μμ ν¨μλ₯Ό ν λΉνλ κ²½μ°
/* * μλλ λ³μ squareμ ν¨μλ₯Ό ν λΉνλ ν¨μ ννμμ λλ€. * μλ°μ€ν¬λ¦½νΈμμ ν¨μλ μΌκΈ κ°μ²΄μ΄κΈ° λλ¬Έμ λ³μμ μ μ₯ν μ μμ΅λλ€. * * ν¨μ ννμμ ν λΉ μ μ μ¬μ©ν μ μμ΅λλ€. * square(7); // --> ReferenceError: Can't find variable: square */ const square = function (num) { return num * num; }; // squareμλ ν¨μκ° μ μ₯λμ΄ μμΌλ―λ‘ (μΌκΈ κ°μ²΄), ν¨μ νΈμΆ μ°μ°μ '()'λ₯Ό μ¬μ©ν μ μμ΅λλ€. output = square(7); console.log(output); // --> 49
[μ½λ] ν¨μ ννμμ λ³μμ ν λΉν λ€μ μ¬μ©ν μ μμ΅λλ€.
μ¬λ¬λΆμ μ΄λ―Έ ν¨μλ₯Ό λ³μμ μ μ₯νλ λ°©λ²(ν¨μ ννμ)μ νμ΅νμ΅λλ€. μμ ν¨μ ννμ(function expression)μ ν¨μ μ μΈμ(function declaration)κ³Ό λ€λ₯΄κ² νΈμ΄μ€ν (Hoisting)μ΄ μ μ©λμ§ μμ΅λλ€.
- νΈμ΄μ€ν μ μ μΈλ μμΉμ κ΄κ³μμ΄ μ΄λμλ ν¨μλ₯Ό μ¬μ©ν μ μλλ‘ ν©λλ€.
- μ½λκ° μ€νλλ κ³Όμ μμ ν¨μ μ μΈλΆλ₯Ό μ½λμ μ΅μλ¨μΌλ‘ λμ΄μ¬λ¦¬λ κ²μ²λΌ 보μ΄κ² ν©λλ€.
ν¨μ μ μΈμμ νΈμ΄μ€ν μ μ§λμΉκ² μμ‘΄νλ©΄, μ½λμ μ μ§ λ³΄μκ° μ½μ§ μμ΅λλ€. μ½λ 리뷰λ λλ²κΉ μ ν λ, μ½λλ₯Ό μμλλ‘ μλ€ κ°λ€ νκ² λ μ μμ΅λλ€. ν¨μ μ μΈμμ μ΄λ μμΉμλ ν¨μλ₯Ό μ μΈν μ μκ³ , ν¨μμ μ€ν μμΉλ μ€μνμ§ μμ΅λλ€. λ°λ©΄μ ν¨μ ννμμ ν¨μμ ν λΉκ³Ό μ€νμ μμΉμ λ°λΌ κ²°κ³Όκ° λ¬λΌμ§κΈ° λλ¬Έμ, μ½λμ μμΉλ₯Ό μ΄λ μ λ μμΈ‘ν μ μμ΅λλ€. νΈμ΄μ€ν μ μ μΈνλ©΄, ν¨μ μ μΈμκ³Ό ν¨μ ννμμ ν¬κ² μ°¨μ΄κ° μμ΅λλ€. λ€λ§, ν¨μ ννμμ κ²½μ°λ ν¨μκ° λ³μμ μ μ₯λ μ μλ€λ μ¬μ€μ λ³΄λ€ λΆλͺ νκ² λ³΄μ¬ μ€λλ€.
κ·Έλ¦¬κ³ ν¨μλ λ³μμ μ μ₯λ λ°μ΄ν°λ₯Ό μΈμλ‘ λ°κ±°λ, λ¦¬ν΄ κ°μΌλ‘ μ¬μ©ν μ μμ΅λλ€. ν¨μλ λ³μμ μ μ₯λ μ μκΈ° λλ¬Έμ ν¨μλ₯Ό μΈμλ‘ λ°κ±°λ, λ¦¬ν΄ κ°μΌλ‘ μ¬μ©ν μ μμ΅λλ€. μ΄μ΄μ§λ μ½ν μΈ λ₯Ό ν΅ν΄ μλ°μ€ν¬λ¦½νΈμ κ³ κΈ μ£Όμ , κ³ μ°¨ ν¨μ(higher order function)λ₯Ό νμ΅ν©λλ€.
κ³ μ°¨ ν¨μλ
κ³ μ°¨ ν¨μ(higher order function)λ ν¨μλ₯Ό μΈμ(argument)λ‘ λ°μ μ μκ³ , ν¨μμ ννλ‘ λ¦¬ν΄ν μ μλ ν¨μμ λλ€. μ΄μ μ½ν μΈ μμ νμΈνλ―μ΄, ν¨μλ λ³μμ μ μ₯ν μ μμ΅λλ€. κ·Έλ¦¬κ³ ν¨μλ, ν¨μλ₯Ό λ΄μ λ³μλ₯Ό μΈμλ‘ μ λ¬λ°μ μ μμ΅λλ€. λ§μ°¬κ°μ§λ‘, ν¨μ λ΄λΆμμ λ³μμ ν¨μλ₯Ό ν λΉν μ μμ΅λλ€. κ·Έλ¦¬κ³ ν¨μλ μ΄ λ³μλ₯Ό 리ν΄ν μ μμ΅λλ€. μ¬κΈ°μ λ³μμ ν λΉνμ§ μκ³ ν¨μλ₯Ό λ°λ‘ μ΄μ©ν μ μμ΅λλ€. μ΄λ€ κ³ μ°¨ ν¨μμ ν¨μλ₯Ό μΈμλ‘ μ λ¬νκ³ , κ³ μ°¨ ν¨μλ ν¨μ μ체λ₯Ό 리ν΄ν©λλ€. λ³μκ° λΉ μ‘μ λΏ, λμΌνκ² λμν©λλ€.
μ΄λ λ€λ₯Έ ν¨μ(caller
)μ μΈμ(argument)λ‘ μ λ¬λλ ν¨μλ₯Ό μ½λ°± ν¨μ(callback function)λΌκ³ ν©λλ€. μ½λ°± ν¨μμ μ΄λ¦μ, μ΄λ€ μμ
μ΄ μλ£λμμ λ νΈμΆνλ κ²½μ°κ° λ§μμ, λ΅μ μ νλ₯Ό λ»νλ μ½λ°±μ΄λΌλ μ΄λ¦μ΄ λΆμ¬μ‘μ΅λλ€.
μ½λ°± ν¨μλ₯Ό μ λ¬λ°μ κ³ μ°¨ ν¨μλ, ν¨μ λ΄λΆμμ μ΄ μ½λ°± ν¨μλ₯Ό νΈμΆ(invoke) ν μ μμ΅λλ€. caller
λ 쑰건μ λ°λΌ μ½λ°± ν¨μμ μ€ν μ¬λΆλ₯Ό κ²°μ ν μ μμ΅λλ€. μμ νΈμΆνμ§ μμ μλ μκ³ , μ¬λ¬ λ² μ€νν μλ μμ΅λλ€. νΉμ μμ
μ μλ£ νμ νΈμΆνλ κ²½μ°λ μ΄νμ μΆ©λΆν μ ν μ μμ΅λλ€.
'ν¨μλ₯Ό 리ν΄νλ ν¨μ'λ λͺ¨μμκ° νΉμ΄ν λ§νΌ, λΆλ₯΄λ μ©μ΄κ° λ°λ‘ μμ΅λλ€. 'ν¨μλ₯Ό 리ν΄νλ ν¨μ'λ₯Ό κ³ μν΄ λΈ λ Όλ¦¬νμ νμ€μΌ 컀리(Haskell Curry)μ μ΄λ¦μ λ°, 컀리 ν¨μλΌκ³ ν©λλ€. λ°λ‘ 컀리 ν¨μλΌλ μ©μ΄λ₯Ό μ¬μ©νλ κ²½μ°μλ, κ³ μ°¨ ν¨μλ μ©μ΄λ₯Ό 'ν¨μλ₯Ό μΈμλ‘ λ°λ ν¨μ'μλ§ νμ ν΄ μ¬μ©νκΈ°λ ν©λλ€. κ·Έλ¬λ μ ννκ² κ΅¬λΆνμλ©΄, κ³ μ°¨ ν¨μκ° μ»€λ¦¬ ν¨μλ₯Ό ν¬ν¨ν©λλ€. μ΄λ² μ λλΆν°λ 'ν¨μλ₯Ό 리ν΄νλ ν¨μ'μ 'ν¨μλ₯Ό μΈμλ‘ λ°λ ν¨μ' λͺ¨λ, μ©μ΄λ₯Ό κ³ μ°¨ ν¨μλ‘ μ¬μ©ν©λλ€.
λ€λ₯Έ ν¨μλ₯Ό μΈμλ‘ λ°λ κ²½μ°
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
λ΄μ₯ κ³ μ°¨ν¨μ(filter, map, reduce)
λ©μλ(filter, map, reduce)λ this
(μλ³Έ λ°°μ΄)λ₯Ό λ³κ²½νμ§ μλλ€π
1. Array.prototype.filter(callback: (element, index: number, array) => thisArg?: any) ;
- 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; // νμλ§μ νν°λ§νλ€ (1μ trueλ‘ νκ°λλ€)
});
// [0] = 1
// [1] = 2
// [2] = 3
// [3] = 4
// [4] = 5
console.log(result); // [ 1, 3, 5 ]
2. Array.prototype.map(callback: (element, index: number, array) => thisArg?: any);
- λ°°μ΄μ μννλ©° κ° μμμ λνμ¬ μΈμλ‘ μ£Όμ΄μ§ μ½λ°± ν¨μμ λ°νκ°(κ²°κ³Όκ°)μΌλ‘ μλ‘μ΄ λ°°μ΄μ μμ±νμ¬ λ°ννλ€. μ΄λ μλ³Έ λ°°μ΄μ λ³κ²½λμ§ μλλ€.
- forEach λ©μλλ λ°°μ΄μ μννλ©° μμ κ°μ μ°Έμ‘°νμ¬ λ¬΄μΈκ°λ₯Ό νκΈ° μν ν¨μμ΄λ©° map λ©μλλ λ°°μ΄μ μννλ©° μμ κ°μ λ€λ₯Έ κ°μΌλ‘ λ§΅ννκΈ° μν ν¨μμ΄λ€.
Array.prototype.map
- μ½λ°± ν¨μμ λ§€κ°λ³μλ₯Ό ν΅ν΄ λ°°μ΄ μμμ κ°, μμ μΈλ±μ€, map λ©μλλ₯Ό νΈμΆν λ°°μ΄, μ¦ thisλ₯Ό μ λ¬ λ°μ μ μλ€.
- IE 9 μ΄μμμ μ μ λμνλ€.
const numbers = [1, 4, 9];
// λ°°μ΄μ μννλ©° κ° μμμ λνμ¬ μΈμλ‘ μ£Όμ΄μ§ μ½λ°±ν¨μλ₯Ό μ€ν
const roots = numbers.map(function (item) {
// λ°νκ°μ΄ μλ‘μ΄ λ°°μ΄μ μμκ° λλ€. λ°νκ°μ΄ μμΌλ©΄ μλ‘μ΄ λ°°μ΄μ λΉμ΄ μλ€.
return Math.sqrt(item);
});
// μ μ½λμ μΆμ½ννμ μλμ κ°λ€.
// const roots = numbers.map(Math.sqrt);
// map λ©μλλ μλ‘μ΄ λ°°μ΄μ λ°ννλ€
console.log(roots); // [ 1, 2, 3 ]
// map λ©μλλ μλ³Έ λ°°μ΄μ λ³κ²½νμ§ μλλ€
console.log(numbers); // [ 1, 4, 9 ]
3. Array.prototype.reduce(callback: (accumulator, currentValue, index: number, array) => accumulator + currentValue);
λ°°μ΄μ μννλ©° κ° μμμ λνμ¬ μ΄μ μ μ½λ°±ν¨μ μ€ν λ°νκ°μ μ λ¬νμ¬ μ½λ°±ν¨μλ₯Ό μ€ννκ³ κ·Έ κ²°κ³Όλ₯Ό λ°ννλ€. IE 9 μ΄μμμ μ μ λμνλ€.
const arr = [1, 2, 3, 4, 5];
/*
previousValue: μ΄μ μ½λ°±μ λ°νκ°
currentValue : λ°°μ΄ μμμ κ°
currentIndex : μΈλ±μ€
array : λ©μλλ₯Ό νΈμΆν λ°°μ΄, μ¦ this
*/
// ν©μ°
const sum = arr.reduce(function (previousValue, currentValue, currentIndex, self) {
console.log(previousValue + '+' + currentValue + '=' + (previousValue + currentValue));
return previousValue + currentValue; // κ²°κ³Όλ λ€μ μ½λ°±μ 첫λ²μ§Έ μΈμλ‘ μ λ¬λλ€
});
console.log(sum); // 15: 1~5κΉμ§μ ν©
/*
1: 1+2=3
2: 3+3=6
3: 6+4=10
4: 10+5=15
15
*/
// μ΅λκ° μ·¨λ
const max = arr.reduce(function (pre, cur) {
return pre > cur ? pre : cur;
});
console.log(max); // 5: μ΅λκ°
π Tomorrow
- κ³ μ°¨ν¨μ 볡μ΅
- μκ³ λ¦¬μ¦ λ¬Έμ νμ΄