Skip to content
This page has been auto-translated and may contain errors.View in English

함수

docs.scrimba.com

장바구니의 항목 가격을 매기고 있다고 생각해 봅시다. 숫자를 받아서 세금을 더하고, 반올림한 후, 통화 기호로 서식을 지정합니다. 그리고 다음 항목, 그 다음 항목에 대해 다시 해야 합니다. 이 네 가지 단계를 모든 곳에 복사하면 버그가 생깁니다. 한 곳에서 반올림을 수정해도 나머지 세 개의 복사본은 여전히 잘못되어 있습니다. 함수를 사용하면 이러한 단계의 블록을 한 번 이름 지정하고 필요할 때마다 실행할 수 있습니다. 이 장에서는 이러한 블록을 작성하고, 입력을 전달하고, 값을 다시 얻는 방법에 관해 설명합니다.

함수 선언 및 호출

**함수**는 언제든지 실행할 수 있는 명명된 코드 블록입니다. 단계를 한 번 작성하고, 이름을 지정한 다음 원하는 만큼 그 이름으로 실행합니다.

function 키워드로 만들 수 있습니다:

js
function greet() {
  console.log("Hi there");
}

이것이 전체 정의이지만 아직 아무 일도 일어나지 않았습니다. 함수를 작성하면 단계를 저장하지만, 실행하지는 않습니다. 실제로 실행하려면 이름 다음에 괄호를 작성하여 호출합니다:

js
greet(); // Hi there
greet(); // Hi there

두 줄, 두 인사, 한 블록의 코드에서. 정의와 호출은 별개의 것이며, 이를 혼동하는 것이 처음으로 사람들을 헷갈리게 하는 첫 번째 원인입니다.

**함수**는 코드 블록을 이름 아래에 래핑하여 필요할 때 실행할 수 있습니다. function 키워드로 한 번 정의한 후 필요한 만큼 여러 번 호출합니다:

js
function logDivider() {
  console.log("----------");
}

logDivider(); // ----------
logDivider(); // ----------

정의는 단계를 설정하지만 아무것도 실행하지 않습니다. 함수는 ()로 호출할 때만 실행됩니다. 이름 자체인 logDivider는 함수 값이고, 괄호는 호출하는 것입니다. 함수를 전달하기 시작하면 즉시 중요해지는데, logDividerlogDivider()는 두 가지 다른 것입니다: 하나는 함수이고 다른 하나는 실행 결과입니다.

**함수**는 이름에 바인딩된 재사용 가능한 코드 블록입니다. 여기서 function 키워드는 함수 선언을 만듭니다: 범위 상단으로 호이스팅되는 명명된 함수로, 작성한 줄 위에서 호출할 수 있으며 여전히 작동합니다.

js
countdown(); // 작동: 선언은 호이스팅됨

function countdown() {
  console.log("Ready");
}

이 호이스팅은 선언 형식에만 적용되며, 이 장의 나중에 함수를 정의하는 다른 방식에서는 공유하지 않습니다. 이름과 호출은 별개의 값입니다: countdown은 함수 자체로 평가되고 (저장, 전달, 비교할 수 있음), countdown()은 함수 실행이 생성하는 무엇이든 평가됩니다. 둘을 혼동하는 것은 "왜 이것이 정의되지 않았는가"라는 혼동의 큰 부분이며, 함수가 다른 함수에 인수로 전달되기 시작하기 전에 이를 분리하는 습관을 들이는 것이 좋습니다.

함수에 하는 일에 대해 명확한 동사 같은 이름을 지정하세요 (greet, logDivider). 변수 이름 지정할 때 취하는 동일한 관심입니다. 10곳에서 호출하는 함수는 이름만큼만 읽기 쉽습니다.

Juno함수 선언 및 호출 함수를 작성하면 단계를 저장합니다. 실행하지는 않습니다. 실행하려면 괄호로 이름으로 호출합니다 (예: greet()). 처음에는 이 분할이 저를 혼동했습니다: 정의는 레시피이고, 호출은 실제로 요리하는 것입니다. 같은 함수를 원하는 만큼 여러 번 호출할 수 있습니다.
Juno함수 선언 및 호출 함수 정의와 호출은 두 가지 별개의 행위입니다. function 블록은 단계를 설정하고 ()를 추가할 때까지 아무것도 실행하지 않습니다. greetgreet()를 명확히 하세요: 하나는 함수 값이고 다른 하나는 실행 결과입니다. 그 차이는 함수를 어딘가에 전달할 때 처음으로 물어뜯습니다.
Juno함수 선언 및 호출function 키워드는 선언을 만들고, 호이스팅되므로 그것이 앉아있는 위치 위에서 호출할 수 있습니다. 이는 이 형식에만 해당됩니다. 표현식과 화살표는 같은 방식으로 호이스팅되지 않습니다. 그리고 countdown은 함수이고 countdown()은 결과이며, 함수를 값으로 전달하기 시작하면서 해당 구별이 덜 중요해집니다.

매개변수 및 반환 값

함수는 뭔가를 공급할 때 더 유용합니다. 공급하는 값은 **매개변수**입니다: 호출할 때 전달하는 모든 것을 나타내는 괄호에 나열된 이름입니다.

js
function greet(name) {
  console.log("Hi " + name);
}

greet("민준"); // Hi 민준
greet("지은"); // Hi 지은

name은 매개변수입니다. greet("민준")을 호출하면, 텍스트 "민준"이 이 실행을 위해 name에 들어갑니다. 하나의 함수, 다른 결과, 전달하는 것에 따라 다릅니다.

지금까지 이 함수들은 뭔가를 인쇄합니다. 종종 함수가 값을 다시 손에 주기를 원해서 나중에 사용할 수 있습니다. 그것이 return이 하는 것입니다:

js
function double(number) {
  return number * 2;
}

const result = double(5);
console.log(result); // 10

return은 함수에서 값을 보냅니다. double(5)10이 되고, 저장하거나, 인쇄하거나, 계속 전달할 수 있습니다. 인쇄는 화면에 값을 표시합니다. 반환은 계속 사용하기 위해 코드에 다시 전달합니다.

함수는 **매개변수**를 통해 입력을 받습니다: 괄호의 이름. 호출 사이트에서 전달하는 값은 이들을 채우는 인수입니다.

js
function priceWithTax(price, rate) {
  return price + price * rate;
}

const total = priceWithTax(40, 0.2);
console.log(total); // 48

pricerate는 매개변수입니다. 400.2는 이 호출의 인수입니다. return 문은 함수를 호출한 사람에게 값을 다시 전달하므로, priceWithTax(40, 0.2)48로 평가되고 total에 저장할 수 있습니다.

로깅과 반환 간의 차이를 명확히 하는 것이 가치 있습니다. console.log를 호출하는 함수는 무언가를 표시하고 undefined로 평가됩니다. return을 사용하는 함수는 프로그램이 계속 작동할 수 있는 값을 생성합니다. return은 또한 즉시 함수를 끝냅니다: 그 이후의 모든 줄은 실행되지 않습니다. return을 완전히 빠뜨리면 함수는 여전히 undefined를 반환하는데, 이는 값을 기대했지만 아무것도 받지 못했을 때 흔한 놀라움입니다.

매개변수는 함수의 명명된 입력입니다. 인수는 호출 사이트에서 이들에 바인딩된 구체적인 값입니다. return 문은 함수의 출력 값을 생성하고 즉시 실행을 종료하므로, 조기 종료로도 작동합니다:

js
function classify(score) {
  if (score < 0) {
    return "invalid";
  }
  if (score >= 60) {
    return "pass";
  }
  return "fail";
}

console.log(classify(72)); // pass
console.log(classify(-3)); // invalid

return은 값을 산출하고 함수를 중지하므로, 하나의 분기가 발동하면 그 아래의 아무것도 실행되지 않습니다. 그 조기 종료 패턴 (먼저 검증하고 종료, 마지막에 주요 경우 처리)은 깊이 중첩된 조건부를 벗어나게 합니다.

실제 코드에서 중요한 구별은 반환하는 함수와 부작용 (콘솔에 쓰기, 자신 밖의 뭔가 변경)만 생성하는 함수 사이입니다. console.log는 부작용을 수행하고 함수는 undefined로 평가됩니다. return은 호출자가 구성할 수 있는 값을 생성합니다. return이 없거나 아무것도 없는 맨 return을 가진 함수는 undefined를 산출합니다. 오직 로깅하는 함수에서 반환된 값에 도달하는 것은 빈번한 버그이며, 수정은 거의 항상 값을 return하고 호출 사이트에서 로깅하는 것입니다.

Juno매개변수 및 반환 값 매개변수는 전달하는 값을 나타내는 괄호의 이름이므로 한 함수는 다른 결과를 줄 수 있습니다. return은 코드가 나중에 사용할 수 있도록 값을 다시 전달합니다. console.log로 인쇄하면 화면에 표시됩니다. 반환하면 나중에 사용하기 위해 다시 전달합니다. 그 차이를 느끼는 데 한 동안 걸렸습니다.
Juno매개변수 및 반환 값 매개변수는 정의의 이름이고, 인수는 호출에서 전달하는 값입니다. return은 호출자에게 값을 전달하고 그 자리에서 함수를 종료합니다. 오직 로깅하는 함수는 undefined로 평가되므로, 값을 기대했지만 아무것도 받지 못했다면, 실제로 반환했는지 확인하세요.
Juno매개변수 및 반환 값return은 값을 산출하고 종료합니다. 이는 검증-후-종료를 깨끗한 패턴으로 만듭니다. console.log 같은 부작용을 하는 것과 값을 반환하는 것 사이의 분할을 감시하세요: 로깅 함수는 undefined로 평가됩니다. 결과에 도달했지만 아무것도 받지 못했다면, 반환해야 할 곳에서 로깅했을 가능성이 높습니다.

화살표 함수

함수를 쓰는 더 짧은 방법이 있으며, **화살표 함수**라고 합니다. 변수에 저장하고 function 키워드 대신 => 화살표를 사용합니다:

js
const add = (a, b) => {
  return a + b;
};

console.log(add(2, 3)); // 5

함수가 이런 단일 표현식일 때, 중괄호와 return을 버리고 화살표가 값을 다시 손에 주도록 할 수 있습니다:

js
const add = (a, b) => a + b;

console.log(add(2, 3)); // 5

둘 다 같은 일을 합니다. 현대 JavaScript에서 화살표 함수를 어디서나 볼 수 있으므로, 모양을 인식하는 것이 도움이 됩니다: 이름, =, 입력, 화살표, 본문.

**화살표 함수**는 함수를 쓰는 더 짧은 구문으로, =>를 사용하여 변수에 저장됩니다:

js
const formatPrice = (amount) => `$${amount.toFixed(2)}`;

console.log(formatPrice(9.5)); // $9.50

본문이 단일 표현식일 때, 화살표 함수는 암시적 반환을 가집니다: 중괄호 없음, return 키워드 없음, 표현식의 값이 자동으로 다시 전달됩니다. 중괄호를 추가하면 일반 함수 본문처럼 작동하며, return을 직접 작성합니다:

js
const formatPrice = (amount) => {
  const rounded = amount.toFixed(2);
  return `$${rounded}`;
};

화살표는 짧고 단일 목적의 함수, 특히 다른 함수에 전달하는 작은 함수 (배열 메서드를 만나면)의 관용적인 선택입니다. 최상위 레벨의 재사용 가능한 명명된 루틴의 경우, 일반 function 선언이 명확하게 읽고 잘 작동합니다. 간결함이 도움이 되고 함수가 작을 때 화살표에 도달하세요.

**화살표 함수**는 =>로 작성된 간단한 함수 표현식입니다. 단일 표현식 본문을 가지면 암시적 반환을 가집니다 (표현식의 값이 return 키워드 없이 반환됨). 중괄호 본문을 가지면 명시적으로 반환하며, 일반 함수와 정확히 같습니다.

js
const applyDiscount = (price, percent) => price * (1 - percent / 100);

console.log(applyDiscount(80, 25)); // 60

함수를 정의하는 세 가지 방법이 함께 존재하며, 차이는 미용이 아닌 실용적입니다:

  • 함수 선언 (function total() {})은 호이스팅되므로, 정의 위에서 호출할 수 있습니다.
  • 함수 표현식 (const total = function () {})은 같은 방식으로 호이스팅되지 않습니다: 변수는 존재하지만 줄이 실행될 때까지 undefined를 보유하므로, 더 일찍 호출하면 throws합니다.
  • 화살표 함수 (const total = () => {})는 호이스팅을 위해 표현식처럼 작동하고 아래의 핵심 규칙 하나를 추가합니다.

화살표를 따로 설정하는 규칙: 그들은 자신의 this를 바인딩하지 않습니다. 일반 함수는 호출 방식에 따라 결정되는 this를 얻습니다. 화살표는 대신 주변 코드에서 this를 상속합니다. 그 구별은 객체에서 메서드를 작성할 때까지 물어뜯지 않으므로, 그 사실을 보유하고 추론은 거기서 착륙합니다.

두 개의 더 많은 도구를 사용할 가치가 있습니다. 기본 매개변수는 인수가 누락될 때 대체를 제공하므로 함수는 예측 가능하게 유지됩니다:

js
const greet = (name = "there") => `Hi ${name}`;

console.log(greet("민준")); // Hi 민준
console.log(greet()); // Hi there

그리고 가장 많이 지불하는 습관: 순수 함수를 선호하세요. 출력이 입력에만 의존하고 자신 밖의 아무것도 변경하지 않는 함수 (부작용 없음). 위의 applyDiscount는 순수합니다: 같은 입력, 같은 결과, 매번입니다. 순수 함수는 격리 상태에서 테스트할 수 있고, 나머지 프로그램을 추적하지 않고 추론할 수 있으며, 놀라움 없이 재사용할 수 있는 함수입니다. 모든 것이 순수할 수는 없습니다 (뭔가는 로깅하고, 가져와야 하며, 상태를 변경해야 함). 하지만 로직을 순수 함수로 밀어 넣고 부작용을 가장자리에 유지하는 것은 언어의 가장 높은 활용 습관 중 하나입니다.

Juno화살표 함수 화살표 함수는 함수를 쓰는 더 짧은 방법으로, function 키워드 대신 =>를 사용하여 변수에 저장됩니다. 본문이 하나의 표현식일 때, 중괄호와 return을 버리고 화살표가 값을 다시 손에 주도록 할 수 있습니다. 이 모양을 계속해서 보게 될 것이므로, 읽기에 편해지는 것이 빠르게 지불합니다.
Juno화살표 함수 화살표는 함수를 쓰는 짧은 형식이며, 단일 표현식 본문은 암시적 반환을 제공합니다: 중괄호 없음, return 없음. 중괄호를 추가하면 일반적으로 return을 작성합니다. 작고 단일 목적의 함수에 도달하세요. 일반 function 선언은 여전히 최상위 레벨 명명된 루틴으로 훌륭하게 읽습니다.
Juno화살표 함수 선언은 호이스팅되고, 표현식과 화살표는 그렇지 않으며, 화살표는 또한 자신의 this를 건너뜁니다. 이는 객체 메서드를 작성할 때만 중요합니다. 누락된 인수에 대해 기본 매개변수를 활용하고, 출력이 입력에만 의존하는 순수 함수로 로직을 밀어 넣으세요. 이는 격리 상태에서 테스트할 수 있고 전체 프로그램을 추적하지 않고 재사용할 수 있는 함수입니다.

함수가 여기서 어떻게 진행되는지

함수는 자신을 반복하는 것을 멈추는 방법입니다: 단계 블록의 이름을 지정하고, 입력을 공급하고, 값을 다시 얻으세요. 일단 그것이 클릭되면, 작성하는 대부분의 코드는 다른 함수를 호출하는 작은 함수가 되며, 각각은 하나의 명확한 작업을 수행합니다.

여기서부터 함수는 어디에나 나타납니다. 배열 메서드에 함수를 전달하여 데이터 리스트를 변환하고, 조건부에서 분기 로직을 구성하는 데 사용하며, 변수로 시작한 이름 지정 규칙에 의존합니다. 다음 번에 코드 블록을 복사하고 있다는 것을 발견할 때, 그것은 대신 함수로 래핑하는 신호입니다.