여느 때처럼 velog를 돌아다니면서 시간을 태우던 중, 면접 질문중에서 꽤나 인상깊었던 질문이 하나 있었습니다.

바로 고차함수가 뭐냐는 물음이었는데요!

 

저도 분명 어디선가 주워서 들어봤긴 한데, 제대로 알고 있지는 않았습니다.

면접에서 가장 위험한 것이 모르는 것보다 잘못 알고 있는 것이잖아요?

그래서 이번 기회에 다시 정리해보기 위해 이렇게 글을 써 보려고 합니다.

 

목차


    0. 일급 시민

    고차 함수를 이해하기 위해서는 먼저 일급 시민 개념에 대해 이해하고 있어야 합니다.

     

    프로그래밍에 있어서 일급 시민의 조건은 아래 세 가지입니다.

    • 변수에 담을 수 있습니다.
    • 함수의 매개변수로 전달할 수 있습니다.
    • 함수의 반환값으로 전달할 수 있습니다.

     

    대부분의 언어에서 기본형 타입의 요소들은 일급 시민의 조건을 만족합니다.

     

    그렇다면 기본형 타입이 아닌 참조형 타입이라면 어떨까요?

    자바스크립트에서의 함수는 Object입니다.

     

    우리는 함수에다가 임의의 프로퍼티를 넣어버리는(!) 굉장히 위험한 짓을 할 수 있습니다. (권장하지 않는 방식이라고 합니다!!)

    이 말은 함수도 결국 객체라는 것을 증명하는 것과 같습니다.

    실제로 함수의 prototype을 찍어보면 Object가 나온다는 것을 확인할 수 있습니다.

     

    함수의 프로토타입은 Object이다!!

     

     

    0.0. 일급 객체와 일급 함수

    여기까지 이해했다면 다음은 쉽습니다.

     

    일급 객체는 무엇일까요?

    • 일급 객체는 변수에 담을 수 있습니다.
    • 일급 객체는 함수의 매개변수로 전달할 수 있습니다.
    • 일급 객체는 함수의 반환값으로 전달할 수 있습니다.

     

    간단하죠?

    바로 이어서 일급 함수는 무엇일까요?

    함수는 객체라고 위에서 증명했으니, 객체 대신 함수를 집어넣으면 끝입니다.

    • 일급 함수는 변수에 담을 수 있습니다.
    • 일급 함수는 함수의 매개변수로 전달할 수 있습니다.
    • 일급 함수는 함수의 반환값으로 전달할 수 있습니다.

     

    세 가지 케이스에 대한 예시를 아래 간단하게 작성해보았습니다.

     

    변수에 함수담기

     

    매개변수에 함수담기

     

    반환값에 함수담기

     


    1. 고차 함수

    그렇다면 이제 고차 함수가 무엇인지에 대해 이해할 수 있게 되었습니다.

    고차 함수함수를 인자로 받거나 함수를 반환함으로써 작동하는 함수를 의미합니다.

     

    대표적으로 Array.prototype.forEach, Array.prototype.map, Array.prototype.filter, Array.prototype.reduce 등이 있습니다.

     

    1.0. forEach

    아래는 forEach의 하나의 예입니다.

    매개변수로 function(element) {console.log(element)}라는 익명함수가 들어갔습니다.

    고차함수를 쓰지 않는다면 for문을 통해서 돌려야 했을테지만, 고차함수를 사용하면 아래와 같이 짧게 표현할 수 있습니다.

    const array1 = ['a', 'b', 'c'];
    
    array1.forEach(element => console.log(element));
    
    // expected output: "a"
    // expected output: "b"
    // expected output: "c"

     

    1.1. map

    이번에는 map을 보겠습니다.

    매개변수로 똑같이 함수를 받습니다.

    const array1 = [1, 4, 9, 16];
    
    // pass a function to map
    const map1 = array1.map(x => x * 2);
    
    console.log(map1);
    // expected output: Array [2, 8, 18, 32]

     

    1.2. closure

    그리고 또 다른 대표적인 예시 중 하나인 클로저를 보겠습니다.

    클로저어떤 함수 A에서 선언한 변수 tmp를 참조하는 내부 함수 B를 외부로 전달한 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 tmp가 메모리에서 사라지지 않는 현상을 의미합니다.

    좀 더 엄밀히 이야기 하면 tmp는 내부함수에 의해서 참조되고 있기 때문에 GC에 의해서 메모리에서 사라지지 않습니다. (처음에는 참조 카운팅 방식을 사용하였으나 순환참조 문제에 의해 현재는 Mark&Sweep 방식을 사용하고 있습니다.)

     

    사실 위 내용은 해당 포스팅 주제에서 좀 벗어나는 부분이 있으므로 이 정도 까지만 확인하고 바로 예제를 살펴보겠습니다.

     

    const cntNumber = () => {
        let count = 0;
        
        const counting = () => {
        	count++;
            console.log(count);
        }
        
        return counting;
    }
    
    const a = cntNumber();
    const b = cntNumber();
    a();
    b();
    a();
    
    // 1
    // 1
    // 2

     

    cntNumber함수는 count라는 변수와 counting이라는 함수를 가지고 있습니다.

    그리고 반환값으로는 counting이라는 함수를 가지죠.

     

    이렇게 함수의 반환값이 함수가 되는데, 편의상 cntNumber를 외부함수, counting을 내부함수라고 부르겠습니다.

    이것 자체만으로도 이미 클로저 현상이 발생했고, 고차 함수의 좋은 예시가 됩니다!

     

    더 자세히 설명하면 a라는 변수에 cntNumber라는 함수를 할당했습니다.

    그리고 b라는 변수에 cntNumber라는 함수를 할당했습니다.

     

    같은 함수를 할당했지만, 클로저는 각자의 환경을 가지게 됩니다.

    이 말은 서로의 실행 컨텍스트의 범위가 달라진다는 의미가 되고, a와 b는 각각의 count변수를 가지게 됩니다.

    그래서 a()와 b()의 동작 결과 출력되는 count는 각각 달라지게 되는 것이죠.

    마지막으로 각각의 count는 외부에서 접근할 수 없으므로 은닉화까지 완성됩니다.

     

     

    이렇게 고차 함수를 사용해서 다양한 방법으로 JavaScript를 사용할 수 있습니다! 신기하죠 :)

     


    2. 참고자료

     

    일급 함수 - 용어 사전 | MDN

    함수를 다른 변수와 동일하게 다루는 언어는 일급 함수를 가졌다고 표현합니다. 예를 들어, 일급 함수를 가진 언어에서는 함수를 다른 함수에 매개변수로 제공하거나, 함수가 함수를 반환할 수

    developer.mozilla.org

     

    클로저 - JavaScript | MDN

    클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.

    developer.mozilla.org

     

    Array.prototype.forEach() - JavaScript | MDN

    forEach() 메서드는 주어진 함수를 배열 요소 각각에 대해 실행합니다.

    developer.mozilla.org

     

    Array.prototype.map() - JavaScript | MDN

    map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

    developer.mozilla.org

     

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기