[Js] Higher Order Function (고차함수)

Seoyoung·2021년 8월 14일
0

Javascript

목록 보기
2/2

자주 사용되고 꼭 알아두어야 하는 JS개념!🙌

고차함수를 이해하기 위해 밑의 2가지 개념에 대해 배워봅시다.

Functional programming

Functional programming은 함수를 다른 함수의 파라미터로 넘길 수도 있고, 반환값(return)으로 함수를 받을 수도 있는 프로그래밍의 형태를 의미합니다. functional programming에서 우리는 function의 관점으로 코드를 생각해요.

First class function

JS는 function을 first-class citizens로 취급합니다. 왜냐하면, function은 JS와 다른 functional programming에서 Object객체이기 때문입니다.
Function = Object (함수 = 객체)!

function greeting() {
	console.log('Hello World')'
}
greeting(); // prints 'Hello World'

함수가 객체임을 증명하는 예제

// we can add properties to functions like we do with objects
greeting.lang = 'English';

console.log(greeting.lang); // print 'English'
  • 위 예문은 JS에서 유효한 문법이지만, function object에 랜덤한 property를 추가하지 않는 것이 좋습니다. 만일 그러고 싶다면, object를 사용하세요.

  • JS에서 object, string, number와 같은 타입으로 할 수 있는 것은 function으로도 할 수 있습니다.
    function을 parameter로 다른 함수에 넘길 수 있고 (call-back function), function을 다른 변수에 할당하거나, 다른 곳으로 넘길 수 있습니다.

    ## 이런 특성은 JS내의 function들이 first-class function으로 불리어지는 이유가 됩니다


Assigning Functions to variables

const square = function(x) {
	return x * x;
}

square(5); // 25
const foo = square;
foo(6); // 36

Passing Functions as parameters

function formalGreeting() {
	console.log("how are you?");
}
function casualGreeting() {
	console.log("what's up?");
}
function greet (type, greetForaml, greetCasual) {
	if (type === 'formal') {
  	 greetForaml();
    } else if (type === 'casual') {
     greetCasual();
    }
  }
  
 greet('casual', formalGreeting, casualGreeting); // what's up?

Higher-Order Functions (고차함수)

A Higher-Order function is a function that receives a function as an argument or returns the function as output. 고차함수는 function을 argument로 받거나, function을 return하는 함수

고차함수를 이용하면 코드를 좀 더 깔끔하고 간결하게 작성할 수 있다.

예를 들어, Array.prototype.map, Array.prototype.filter, Array.prototype.reduce가 언어 내부에 포함된 (bulit in) 고차함수

1. Array.prototype.map

map() 메소드는 입력으로 들어온 배열 내 모든 element를 인자argument로 제공받는 call-back fucntion을 호출함으로 새로운 배열을 만듭니다. map() 메소드는 call-back함수에서 모든 반환된 값을 가져올 것입니다. 그리고 그 값들을 이용한 새로운 배열 하나를 만들어냅니다.

  • map() 메소드로 전해진 call-back function은 "element", "index", "array" 3가지의 인자를 갖고 있습니다.

Ex1
배열내부의 각각의 숫자 값이 2배가 되는 배열을 만들고 싶을 때

1) without higher-order function

const arr1 = [1, 2, 3];
const arr2 = [];
for(let i = 0; i < arr1.length; i++) {
  arr2.push(arr1[i] * 2);
}
// prints [ 2, 4, 6 ]
console.log(arr2);

2) with higher-order function

const arr1 = [1, 2, 3];
const arr2 = arr1.map(function(item) {
  return item * 2;
 });
 
 console.log(arr2);

3) with arrow function

const arr1 = [1, 2, 3];
const arr2 = arr1.map(item => item * 2);
console.log(arr2);

Ex2
생을 정보를 갖고 있는 배열으로 사람들의 나이를 계산하고 싶을 때

1) without higher-order function

const birthYear = [1975, 1997, 2002, 1995, 1985];
const ages = [];

for(let i = 0; i < birthYear.length; i++) {
  let age = 2021 - birthYear[i];
  ages.push(age);
}

console.log(ages);

2) with higher-order function

const birthYear = [1975, 1997, 2002, 1995, 1985];
const ages = birthYear.map(function(year) {
 return 2021 - year;
}

console.log(ages);

3) with arrow function

const birthYear = [1975, 1997, 2002, 1995, 1985];
const ages = birthYear.map(year => 2021 - year);

console.log(ages);

2. Array.prototype.filter

filter() 메소드는 call-back function에 의해 제공된 test를 통과한 모든 element를 가진 새로운 배열을 만듭니다.

  • map() 메소드로 전해진 call-back function은 "element", "index", "array" 3가지의 인자를 갖고 있습니다.

Ex1
이름,나이 property를 가진 객체object에서 18살 이상의 사람만 filtering해서 새로운 배열을 만들고 싶을 때

1) without higher-order function

const persons = [
  { name: 'Peter', age: 16 },
  { name: 'Mark', age: 18 },
  { name: 'John', age: 27 },
  { name: 'Jane', age: 14 },
  { name: 'Tony', age: 24},
];

const fullAge = [];
for(let i = 0; i < persons.length; i++) {
  if(persons[i].age >= 18) {
   fullAge.push(persons[i]);
  }
 }
 console.log(fullAge);

2) with higher-order function

const persons = [
  { name: 'Peter', age: 16 },
  { name: 'Mark', age: 18 },
  { name: 'John', age: 27 },
  { name: 'Jane', age: 14 },
  { name: 'Tony', age: 24},
];

const fullAge = persons.filter(person => person.age >= 18);
console.log(fullAge);

3. Array.prototype.reduce

reduce() 메소드는 호출하는 배열의 각각의 멤버에 대해서 call-back function을 실행하고, 하나의 결과 값만 내보냅니다. reduce() 메소는 다음의 2가지 parameter를 받습니다 => reducer function(call-back) & 초기값(initialValue)옵션

reducer function(call-back)
4가지 parameter : accumulator, currentValue, currentIndex, sourceArray

  • 만일 initialValue가 제공되었다면, 그 후에 accumulator는 initialValue와 같아지고 currentValue는 배열의 첫번째 요소가 됩니다.
  • 만일 initialValue가 제공되지 않았다면, 그 후에 accumulator는 배열의 처음 요소와 동일해지고, currentValue는 배열의 두번째 요소가 됩니다.

Ex1
숫자 배열의 합을 구하는 예제

1) without higher-order function

const arr = [5, 7, 1, 8, 4];

let sum = 0;

for(let i = 0; i <arr.length; i++) {
  sum = sum + arr[i];
 }
 
 console.log(sum); // 25

2) with higher-order function

const arr = [5, 7, 1, 8, 4];

const sum = arr.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
});

console.log(sum); // 25

배열 내부의 각 값에 대해 reducer function가 호출되는 모든 순간에, accumulator는 reducer function으로부터 반환된 이전 연산의 결과를 갖고 있습니다. 그리고 currentValue는 배열의 현재 값으로 setting됩니다. 마지막 결과값은 sum 변수에 저장됩니다.

함수에 초기 값을 제공하는 것도 가능합니다.

const arr = [5, 7, 1, 8, 4];

const sum = arr.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
}, 10);

// prints 35
console.log(sum);

결론

Higher-order function 더 연습해보자!

profile
@ronachoiz

0개의 댓글