function

function声明将新函数的绑定创建到给定的名称。

您还可以使用function表达式定义函数。

试一试

语法

js
function name(param0) {
  statements
}
function name(param0, param1) {
  statements
}
function name(param0, param1, /* …, */ paramN) {
  statements
}

参数

名称

函数名称。

param 可选

函数的形式参数的名称。不同引擎中允许的最大参数数量有所不同。有关参数的语法,请参阅函数参考

statements 可选

构成函数体的语句。

描述

function声明创建一个Function对象。每次调用函数时,它都会返回最后执行的return语句指定的值,如果到达函数体末尾则返回undefined。有关函数的详细信息,请参阅函数

function声明的行为类似于varlet的混合。

  • let类似,在严格模式下,函数声明的作用域限于最紧密的包含块
  • let类似,模块顶层或严格模式下块中的函数声明不能被任何其他声明重新声明
  • var类似,脚本顶层(严格或非严格)的函数声明成为globalThis上的属性。脚本或函数体(严格或非严格)顶层的函数声明可以被另一个functionvar重新声明。
  • 与两者类似,函数声明可以重新赋值,但您应该避免这样做。
  • 与两者都不相同,函数声明会被提升,连同其值一起,并且可以在其作用域内的任何地方调用。

块级函数声明

警告:非严格模式下,块内的函数声明行为异常。仅当您处于严格模式时才在块中声明函数。

函数可以有条件地声明——也就是说,函数语句可以嵌套在if语句中。但是,在非严格模式下,结果在不同的实现之间不一致。

js
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主体是否实际执行,作用域和提升效果都不会改变。

js
console.log(
  `'foo' name ${
    "foo" in globalThis ? "is" : "is not"
  } global. typeof foo is ${typeof foo}`,
);
if (true) {
  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

严格模式下,级函数声明的作用域限于该块,并且会被提升到块的顶部。

js
"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

提升

JavaScript中的函数声明会被提升到封闭函数或全局作用域的顶部。您可以在声明函数之前使用它

js
hoisted(); // Logs "foo"

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

请注意,函数表达式不会被提升

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

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

重新声明

function声明是否可以在相同的作用域中重新声明取决于它包含在什么作用域中。

在脚本的顶层,function声明的行为类似于var,并且可以被另一个functionvar重新声明,但不能被letconstclass重新声明。

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

function声明被var重新声明时,var声明的初始化程序始终会覆盖函数的值,无论它们的相对位置如何。这是因为函数声明在任何初始化程序被评估之前就被提升,因此初始化程序后来出现并覆盖了该值。

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

在函数体顶层,function也表现得像var,并且可以被重新声明或与参数具有相同的名称。

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

foo(2); // Logs "function"

在模块的顶层或严格模式下的块中,function声明的行为类似于let,并且不能被任何其他声明重新声明。

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

catch块中的function声明不能与catch绑定的标识符具有相同的名称,即使在非严格模式下也是如此。

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

示例

使用函数

以下代码声明了一个函数,该函数在给出三种产品的销售单位数量时返回总销售额。

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

规范

规范
ECMAScript语言规范
# sec-function-definitions

浏览器兼容性

BCD表格仅在浏览器中加载

另请参阅