All Posts

higher order function, 고차함수

정의

고차 함수는 함수를 argument로 받아서 함수를 리턴하는 함수를 말한다.

예제

함수를 argument로 받는 함수

홀수 인지 확인하는 고차함수를 아래와 같이 만들어 보자.

function isOdd(num, fn) {
  return fn(num) % 2 === 1
}

fn이라는 argument로 함수를 받고 있고, 그에 대한 결과를 리턴하고 있다. 위 함수는 아래와 같은 형태로 사용 가능하다.

function divideByTwo(num) {
  return num / 1
}

isOdd(10, divideByTwo) // true

isOdd(11, divideByTwo) // false

함수를 리턴하는 함수

function add(num1) {
  return function (num2) {
    return num1 + num2
  }
}
add(1)(2) // 3

const num = add(1) // 1만 담고 있는 함수를 리턴
num(2) // 을 위해서 호출해서 2를 더함 3

좀 더 실용적인 예제

가장 일반적인 예제로는 object validator가 있다. 해당 object가 유효한지를 확인하는 것인데, 회원가입의 그것과도 비슷하다.

예를 들어 아래와 같은 객체가 있다고 가정해보자.

const user = {
  age: 18,
  password: 'qhdks1234!@#$',
  gender: 'F',
  agreed: true,
}
  • age는 18세 이상이어야 한다.
  • password는 10자리 이상이여야 한다.
  • genderF 또는 M이여야 한다.
  • agreed는 true 여야 한다.

위 요구 사항을 각각 함수로 만들어 보자.

function validAge(user) {
  return user.age >= 18
}

function validPassword(user) {
  return user.password.length >= 10
}

function agreed(user) {
  return user.agreed
}

function validGender(user) {
  console.log(user.gender, ['T', 'F'].includes(user.gender))
  return ['T', 'F'].includes(user.gender)
}

그리고 isValid라고 불리우는 고차함수를 만들어야 한다. 첫번째 객체로는 user를 받을 것이며, 그 이후에는 n개의 유효성 체크를 하는 함수를 받아서 이를 확인할 것이다.

function isValid(user, ...validators) {
  for (const validator of validators) {
    if (!validator(user)) return false
  }
  return true
}

테스트를 한번 해보자.

const user1 = {
  age: 18,
  password: 'qhdks1234!@#$',
  gender: 'F',
  agreed: true,
}

isValid(user, validAge, validPassword, agreed, validGender) // true
const user2 = {
  age: 12,
  password: 'qhdks1234!@#$',
  gender: 'F',
  agreed: true,
}

isValid(user2, validAge, validPassword, agreed, validGender) // false
const user3 = {
  age: 20,
  password: 'qhdks1234!@#$',
  gender: 'G',
  agreed: true,
}

isValid(user3, validAge, validPassword, agreed, validGender) // false

validator 만들기

user 외에도 여러 종류의 validator를 만든다면, 이것 또한 고차함수르르 만들어서 해결이 가능하다.

function createValidator(...validators) {
  return function (obj) {
    for (const validator of validators) {
      if (!validator(obj)) return false
    }
    return true
  }
}
const userValidator = createValidator(
  validAge,
  validPassword,
  validGender,
  agreed,
)

userValidator(user1) // true
userValidator(user2) // false
userValidator(user3) //  false