자바스크립트 교과서 - 10. 함수

Seoyong Lee·2023년 10월 5일
0

개발 공부

목록 보기
12/21
post-thumbnail

함수의 기원

최초의 프로그램은 루틴(routine)이라고 불렸습니다. 루틴은 주문서의 나열이었습니다. …단일 목록 형태로 루틴을 관리하는 것은 굉장히 어려웠습니다. 동일한 명령어 목록이 여러 루틴에서 발견되기도 하고, 같은 루틴에서 같은 명령어 목록이 여러번 나오기도 했으니까요. 그래서 서브루틴(subroutine)이 만들어졌습니다. 그리고 유용한 여러 서브루틴을 묶어서 라이브러리라고 부르기 시작했습니다.

…수학적인 함수와 서브루틴이 연관성이 있다는 사실이 알려지면서, 포트란 II에는 SUBROUTINE 선언과 서브루틴을 쓰기 위한 CALL 문, 그리고 표현식에 값을 주입할 수 있도록 값을 반환할 수 있는 FUNCTION 선언문이 도입되었습니다.

더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p137.

  • 최초의 함수는 서브루틴에서 기원한다. 서브루틴이 반복되는 것들을 묶어보려는 시도에서 나왔던 것 처럼 함수도 한 번 정의하면 반복해서 호출할 수 있다.
  • 함수는 다음과 같이 코드의 재사용이라는 측면에서 매우 유용하다.

함수를 사용하지 않고 같은 코드를 중복해서 여러 번 작성하면 그 코드를 수정해야 할 때 중복된 횟수만큼 코드를 수정해야 한다. 따라서 중복된 횟수에 비례해서 코드 수정에 걸리는 시간이 증가한다. …코드의 중복을 억제하고 재사용성을 높이는 함수는 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.

이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p156.


자바스크립트의 함수

  • 자바스크립트의 함수는 입력을 전달받는 매개변수(parameter), 인수(argument), 반환값(return value)으로 구성된다.
function add(x, y) { // 매개변수 parameter x, y
	return x + y; // 반환값 return value
}
add(2, 5); // 인수 argument 2, 5

자바스크립트 함수는 매개변수화(parameterized)됩니다. 함수 정의에는 매개변수(parameter)라고 불리는 식별자 리스트가 있는데, 이들은 함수 바디에서 로컬 변수처럼 동작합니다.

데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022), p211.

  • 매개변수와 인수는 서로 다른 개념이다. 함수 내부에서는 로컬 변수처럼 동작하는 매개변수를 바라보지만 실제 함수의 호출 시에는 인수라는 값을 넘긴다.

함수의 정의(생성)

  • 자바스크립트는 다음 4가지 방법으로 함수를 정의하며 각 방식마다 조금씩 차이가 있다.
    • 함수 선언문
      - 함수 이름을 생략할 수 없으며 표현식이 아닌 문으로 취급된다.
      - 호이스팅(hoisting)을 통해 함수 선언문 이전에도 호출이 가능하다. 즉, 자바스크립트 엔진은 런타임 이전에 미리 함수 이름과 동일한 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.
      - 선언 이전에 호출이 가능한 부분은 조금 이상할 수 있다. 실제로 더글라스 크락포드의 경우에는 함수 표현식만 사용할 것을 권장한다.

      function add(x, y) {
      	return x + y;
      }
    • 함수 표현식
      - 자바스크립트의 함수는 일급 객체이므로 함수를 변수에 할당할 수 있다.

      const add = function(x, y) {
      	return x + y;
      };
    • Function 생성자 함수
      - 빌트인 함수인 Function 생성자를 이용할 수 있으나 클로저를 생성하지 않는 등, 다른 정의 방법과 다르게 동작하므로 바람직하지 않은 방법이다.

      const add = new Function('x', 'y', 'return x + y');
    • 화살표 함수(ES6)
      - 기존 함수에서 표현과 내부 동작이 간략화된 방식으로, 기존과 this 바인딩 방식이 다르며 prototype 프로퍼티가 없고 arguments 객체를 생성하지 않는다.

      const add = (x, y) => x + y;

함수의 호출

  • 함수는 호출 표현식(괄호)을 통해 삼수 또는 메서드로 호출된다.
  • 일반적으로 return 문 다름 표현식이 함수의 반환 값이며, return 문에 값이 없거나 return 문 자체가 없다면 반환 값은 undefined이다.
const add = function(x, y) {
	return x + y;
};

const res = add(1, 2); // 함수 호출

함수가 호출되면 활성 객체(activation object)가 만들어집니다. 활성 객체는 눈에 보이지 않습니다. 숨겨진 데이터 구조로서 호출된 함수의 반환 주소와 실행에 필요한 정보를 저장하고 이를 호출된 함수에 바인딩해 줍니다.

C와 같은 언어에서는 활성 객체가 스택에 저장됩니다. 그리고 함수가 종료되고 반환되면 스택에서 제거합니다. 자바스크립트는 좀 다르게 동작합니다. 자바스크립트는 활성 객체를 다른 객체와 마찬가지로 힙에 저장합니다. 함수가 종료된다고 활성 객체를 자동으로 비활성화하진 않습니다. 활성 객체는 해당 객체에 대한 참조가 있는 한 계속 살아있으며, 다른 객체와 마찬가지로 가비지 컬렉터에 의해 처리됩니다.

더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p139.


함수의 형태

즉시실행함수

  • 즉시실행함수(IIFE, Immediately Invoked Function Expression)는 함수의 정의와 동시에 즉시 호출되는 함수로, 단 한 번만 호출되며 다시 호출할 수 없다.
  • 즉시실행함수는 불필요한 전역 변수 생성을 줄이고 private한 변수를 만들 수 있다는 장점을 가진다.
(() => {
  // 초기화 코드
  let firstVariable;
  let secondVariable;
})();

// firstVariable와 secondVariable은 이 함수 실행 후에 사용할 수 없다.

재귀함수

  • 함수가 자기 자신을 호출하는 것을 재귀 호출(recursive call)이라 한다. 재귀 함수(recursive function)는 재귀 호출을 수행하는 함수를 말한다.
  • 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다. 탈출 조건이 없으면 무한 호출되어 스택 오버플로 에러(Maximum call-stack size exceeded)가 발생한다.
function loop(x) {
  if (x >= 10)
    // "x >= 10" 는 탈출 조건 ("!(x < 10)"와 동일)
    return;
  // 뭔가 합니다.
  loop(x + 1); // 재귀 호출
}
loop(0);

중첩함수

  • 함수 내부에 정의된 함수를 중첩함수(nested function) 혹은 내부함수(inner function)라 한다.
  • 중첩 함수는 함수 내부에서만 호출할 수 있으며 보통 헬퍼함수(helper function)의 역할을 한다.
  • 중첩함수는 클로저를 생성한다. 클로저는 후에 따로 다룰 예정이다.
function addSquares(a, b) {
  function square(x) {
    return x * x;
  }
  return square(a) + square(b);
}
a = addSquares(2, 3); // 13

콜백함수

  • 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수(callback function)라고 한다.
  • 매개변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수 자신은 고차함수(HOF)라고 한다. 두 개념의 차이를 잘 알아두자.

함수형 프로그래밍

  • 함수형 프로그래밍(functional programming)은 데이터 처리를 수학적 함수의 계산으로 취급하고 상태의 변경을 피하기 위해 함수의 응용을 강조하는 패러다임이다.
  • 자바스크립트는 함수형 프로그래밍 언어는 아니지만 함수형 프로그래밍 기법을 사용할 수 있다. 배열에서 살펴보았던 고차함수가 바로 이러한 함수형 프로그래밍의 예로 볼 수 있다.

자바스크립트는 리스프(Lisp)나 하스켈(Haskell) 같은 함수형 프로그래밍 언어는 아니지만, 함수를 객체처럼 조작할 수 있으므로 함수형 프로그래밍 기법을 사용할 수 있습니다. map()과 reduce() 같은 배열 메서드는 특히 함수형 프로그래밍 스타일에 알맞습니다.

데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022), p246.

  • 함수형 프로그래밍의 또 하나 중요한 개념으로 순수 함수(pure function)가 있다.

순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환하는 함수다. 즉, 순수 함수는 어떤 외부 상태에도 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에게만 의존해 값을 생성해 반환한다.

…함수형 프로그래밍은 결국 순수 함수를 통해 부수 효과를 최대한 억제해 오류를 피하고 프로그램의 안정성을 높이려는 노력의 일환이라고 할 수 있다. 자바스크립트는 멀티 패러다임 언어이므로 객체지향 프로그래밍 뿐만 아니라 함수형 프로그래밍을 적극적으로 활용하고 있다.

이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p187-188.


References

데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022)
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020)
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017)
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020)

0개의 댓글