function 선언

function 선언

function 선언은 새 함수를 주어진 이름에 바인딩합니다. function 표현식을 사용해 함수를 정의할 수도 있습니다.

출처: function

본문

function 선언은 새 함수를 주어진 이름에 바인딩합니다. function 표현식(function expression)을 사용해 함수를 정의할 수도 있습니다. 이 기능은 널리 확립되어 있으며 여러 브라우저에서 지원됩니다.

구문 (Syntax)

function name(param0) {
  statements
}
function name(param0, param1) {
  statements
}
function name(param0, param1, /* …, */ paramN) {
  statements
}
  • name: 함수 이름입니다.
  • paramN: 함수의 형식 매개변수 이름입니다. 최대 인자 수는 엔진마다 다릅니다. 매개변수 구문은 Functions 참조를 보세요.
  • statements: 함수 본문을 구성하는 문들입니다.

설명 (Description)

함수 선언은 Function 객체를 만듭니다. 함수가 호출될 때마다 마지막으로 실행된 return 문이 지정한 값을 반환하거나, 함수 본문의 끝에 도달하면 undefined를 반환합니다.

함수 선언은 varlet의 혼합처럼 동작합니다.

  • let처럼, strict 모드에서는 함수 선언이 가장 가깝게 포함하는 블록에 스코프됩니다.
  • let처럼, 모듈의 최상위 수준 또는 strict 모드의 블록 내 함수 선언은 다른 어떤 선언에 의해서도 재선언될 수 없습니다.
  • var처럼, 스크립트(strict 또는 non-strict)의 최상위 수준 함수 선언은 globalThis의 속성이 됩니다. 스크립트나 함수 본문(strict 또는 non-strict)의 최상위 수준 함수 선언은 다른 함수나 var에 의해 재선언될 수 있습니다.
  • 둘 다처럼, 함수 선언은 재할당될 수 있지만 그렇게 하는 것을 피해야 합니다.
  • 둘 다와 달리, 함수 선언은 값과 함께 호이스팅(hoisted)되어 스코프 어디에서든 호출될 수 있습니다.

블록 수준 함수 선언

경고: non-strict 모드에서 블록 내 함수 선언은 이상하게 동작합니다. 블록에서 함수를 선언하는 것은 strict 모드에서만 하세요.

함수는 조건부로 선언될 수 있습니다. 즉, 함수 문이 if 문 안에 중첩될 수 있습니다. 그러나 non-strict 모드에서는 결과가 구현 간에 일관되지 않습니다.

console.log(
  `'foo' name ${
    "foo" in globalThis ? "is" : "is not"
  } global. typeof foo is ${typeof foo}`,
);
if (false) {
  function foo() {
    return 1;
  }
}

// In Chrome:
// 'foo' name is global. typeof foo is undefined
//
// In Firefox:
// 'foo' name is global. typeof foo is undefined
//
// In Safari:
// 'foo' name is global. typeof foo is function

if 본문이 실제로 실행되는지 여부와 관계없이 스코프와 호이스팅 효과는 변하지 않습니다. strict 모드에서는 블록 수준 함수 선언이 그 블록에 스코프되고 블록의 맨 위로 호이스팅됩니다.

"use strict";

{
  foo(); // Logs "foo"
  function foo() {
    console.log("foo");
  }
}

console.log(
  `'foo' name ${
    "foo" in globalThis ? "is" : "is not"
  } global. typeof foo is ${typeof foo}`,
);
// 'foo' name is not global. typeof foo is undefined

호이스팅 (Hoisting)

JavaScript의 함수 선언은 포함하는 함수 또는 전역 스코프의 맨 위로 호이스팅됩니다. 선언하기 전에 함수를 사용할 수 있습니다.

hoisted(); // Logs "foo"

function hoisted() {
  console.log("foo");
}

함수 표현식은 호이스팅되지 않는다는 점에 유의하세요.

notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function () {
  console.log("bar");
};

재선언 (Redeclarations)

함수 선언을 같은 스코프에서 재선언할 수 있는지 여부는 그것이 포함된 스코프에 따라 달라집니다.

스크립트의 최상위 수준에서 함수 선언은 var처럼 동작하며 다른 함수나 var에 의해 재선언될 수 있지만, let, const, class에 의해서는 재선언될 수 없습니다.

function a(b) {}
function a(b, c) {}
console.log(a.length); // 2
let a = 2; // SyntaxError: Identifier 'a' has already been declared

함수 선언이 var에 의해 재선언되면, var 선언의 초기화자는 상대 위치와 관계없이 항상 함수의 값을 덮어씁니다. 함수 선언은 어떤 초기화자도 평가되기 전에 호이스팅되므로 초기화자가 나중에 와서 값을 덮어쓰기 때문입니다.

var a = 1;
function a() {}
console.log(a); // 1

함수 본문의 최상위 수준에서 functionvar처럼 동작하며 매개변수와 같은 이름으로 재선언되거나 이름이 같을 수 있습니다.

function foo(a) {
  function a() {}
  console.log(typeof a);
}

foo(2); // Logs "function"

strict 모드의 모듈 또는 블록 최상위 수준에서 함수 선언은 let처럼 동작하며 다른 어떤 선언에 의해서도 재선언될 수 없습니다.

// Assuming current source is a module
function foo() {}
function foo() {} // SyntaxError: Identifier 'foo' has already been declared

catch 블록 내의 함수 선언은 non-strict 모드에서도 catch로 바인딩된 식별자와 같은 이름을 가질 수 없습니다.

try {
} catch (e) {
  function e() {} // SyntaxError: Identifier 'e' has already been declared
}

예제: function 사용하기

다음 코드는 세 제품의 판매 수량이 주어졌을 때 총 판매액을 반환하는 함수를 선언합니다.

function calcSales(unitsA, unitsB, unitsC) {
  return unitsA * 79 + unitsB * 129 + unitsC * 699;
}

더 알아보기