모던 자바스크립트 Deep Dive 12장

seokji·2022년 10월 7일
0

DeepDive

목록 보기
6/6
post-thumbnail

12장 함수


12.1 함수란?

함수는 자바스크립트에서 가장 중요한 핵심 개념이다.

함수는 입력을 받아 출력을 내보내는 일련의 과정을 정의한 것이다.
함수는 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.

함수 내부로 입력을 전달받는 변수를 매개변수, 입력을 인수, 출력을 반환값이라 한다.

fuction add(x, y) { // add는 함수 이름, x y는 매개변수
  return x + y; // 반환값
}

add(2,5) // 2, 5 인수

함수는 함수 정의를 통해 생성한다.

정의된 함수는 호출을 통해 동작한다.


12.2 함수를 사용하는 이유

함수는 여러 번 호출할 수 있다. 즉 코드의 재사용이 가능하다.

함수는 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.


12.3 함수 리터럴

함수는 객체 타입의 값이다. 함수도 리터럴로 생성할 수 있다.
함수 리터럴은 function 키워드, 함수 이름, 매개 변수 목록, 함수 몸체로 구성된다.

함수는 객체지만 일반 객체와 다르게 호출할 수 있다.


12.4 함수 정의

함수를 정의하는 방법은 4가지가 있다.

1. 함수 선언문

// 함수 선언문
function fuction add(x, y) {
    return x + y;
}

함수 선언문은 리터럴과 형태가 동일하다. 하지만 함수 이름을 생략할 수 없다.

함수 선언문은 표현식이 아닌 문이다.
자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성, 거기에 함수 객체를 할당한다.

✨ 함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다.

2. 함수 표현식

자바스크립트의 함수는 값처럼 변수에 할당 할 수도 있고 프로퍼티의 값이 될 수도 있으며 배열의 요소가 될 수도 있다.

이와 같은 성질을 갖는 객체를 일급 객체라 한다. 자바스크립트의 함수는 일급 객체다.

함수 객체를 변수에 할당하는 정의 방식을 함수 표현식이라 한다.

var add = function (x, y) {
  return x + y;
};

함수 표현식은 함수 이름을 생략한다. 이런 함수를 익명 함수라 한다.

3. 함수 생성 시점과 함수 호이스팅

함수 선언문과 함수 표현식으로 정의한 함수의 생성 시점은 다르다.

  • 선언문은 런타임 이전에 먼저 실행 된다. 즉 함수 선언문으로 정의한 함수는 런타임 이전에 객체가 생성된다.
    → 함수 선언문 이전에 함수를 참조할 수 있고 호출할 수 있다.

✨ 함수 선언문이 코드 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 호이스팅이라고 한다.

  • 함수 표현식으로 정의된 함수는 함수 호이스팅이 아닌 변수 호이스팅이 발생한다.
    → 함수 표현식 이전에 함수를 참조하면 undefined로 평가된다.

4. 화살표 함수

ES6에 도입된 화살표 함수=>를 사용해 좀 더 간결하게 함수를 선언할 수 있다.
화살표 함수는 항상 익명 함수이다.

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

12.7 다양한 함수의 형태

1. 즉시 실행 함수 IIFE

정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수라고 한다. 단 한번만 호출되며 다시 호출할 수 없다.

즉시 실행 함수는 반드시 그룹 연산자 (...)로 감싸야 한다.

// 즉시 실행 함수 정의
(function () {})();

(function () {})();

2. 재귀 함수

함수가 자기 자신을 호출하는 것을 재귀 호출이라 한다. 재귀 함수는 자기 자신을 호출하는 함수를 말한다.

재귀 함수는 반복되는 처리를 위해 사용한다.

function countdown(n) {
  if (n < 0) return;
  console.log(n);
  countdown(n - 1);
}
countdown(10); // 0 1 2 3 4 5 6 7 8 9 10

재귀 함수를 사용하면 반복문 없이 반복 처리를 구현할 수 있다.

팩토리얼은 재귀 함수로 구현할 수 있다.

// 팩토리얼 n! = 1 * 2 * ... * (n-1) * n
function factorial(n) {
  // 탈출 조건 : n이 1 이하일 때 재귀 호출 멈춤
  if (n <= 1) return 1;

  // 재귀 호출
  return n * factorial(n - 1);
}

console.log(factorial(1)); // 1
console.log(factorial(2)); // 2
console.log(factorial(3)); // 6
console.log(factorial(4)); // 24
console.log(factorial(5)); // 120

✨ 재귀 함수는 자신을 무한 호출한다. 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다.

✨ 재귀 함수는 무한 반복에 빠질 위험이 있으니 반복문을 사용하는 것 보다 더 직관적일 경우에 사용하는 것이 바람직하다.

3. 중첩 함수

함수 내부에 정의된 함수를 중첩 함수 또는 내부 함수라 한다. 그 중첩 함수를 포함하는 함수를 외부 함수라 한다. 중첩 함수는 외부 함수 내부에서만 호출 가능하다.

✨ 중첩 함수는 외부 함수를 돕는 헬퍼 함수다.

function outer() {
  var x = 1;

  function inner() {
    var y = 2;
    console.log(x + y);
  }

  inner();
}

outer(); // 3

4. 콜백 함수

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라 한다.
콜백 함수를 전달 받은 함수를 고차 함수(Higher Order Function HOF)라고 한다.

고차 함수는 콜백 함수의 호출 시점을 결정해서 호출하며 필요에 따라 콜백 함수에 인수를 전달할 수 있다.

콜백 함수는 비동기, 배열 고차 함수에서 사용된다.


5. 순수 함수와 비순수 함수

  • 순수 함수 : 외부 상태 의존 x, 변경 x, 부수 효과가 없는 함수
var count = 0; // 현재 카운트 상태

// 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환
function increase(n) {
  return ++n;
}

count = increase(count);
console.log(count); // 1

count = increase(count);
console.log(count); // 2
  • 비순수 함수 : 부수 효과가 있는 함수
var count = 0; // 현재 카운트 상태

function increase() {
  return ++count; // 외부 상태에 의존하며 외부 상태를 변경
}

// 외부 상태를 변경하므로 상태 변화 추적이 어려움
increase();
console.log(count); // 1

increase();
console.log(count); // 2

✨ 외부 상태를 변경하면 상태 변화를 추적하기 어려워진다. 따라서 순수 함수를 사용하는 것이 좋다.


✔ 배운점

순수 함수와 비순수 함수에 대하여 알 수 있었다.
비순수 함수는 코드의 복잡성을 증가하고 상태 추적이 어렵다는 단점이 있다.
외부 상태를 변경하는 것과 부수 효과를 일으킨다는 점이 코드를 복잡하게 만들 것 같다.

0개의 댓글