返回

函数声明为什么可以在声明前被调用**

前端

引言

在 JavaScript 中,函数声明有一个奇怪的行为:可以在它们被声明之前调用。这对于习惯于其他编程语言的人来说可能令人惊讶,但对于 JavaScript 来说这是完全正常的。本文将解释这种行为背后的原因,并探讨函数声明与函数表达式的差异。

函数声明与函数表达式

在 JavaScript 中,有两种声明函数的方法:函数声明和函数表达式。

函数声明 使用 function ,后面跟函数名和括号内的参数列表,最后是函数体(用大括号括起来)。例如:

function myFunction(param1, param2) {
  // 函数体
}

函数表达式 使用一个函数字面量,它是一个匿名函数,用括号括起来,后面跟参数列表和函数体。例如:

const myFunction = function(param1, param2) {
  // 函数体
};

声明前调用

函数声明可以先于它们的声明被调用,这是因为 JavaScript 引擎在执行代码时会执行以下步骤:

  1. 预编译阶段: 在此阶段,解析器会扫描代码并创建标识符解析树(Identifier Resolution Tree)。此树包含代码中所有标识符(变量、函数和类)的列表。
  2. 变量环境创建: 引擎创建一个变量环境,其中包含所有已声明的变量和函数。即使在声明之前,函数声明也会被添加到此环境中。
  3. 代码执行: 引擎逐行执行代码。当遇到函数调用时,它会在变量环境中查找该函数,即使该函数尚未声明。

函数声明式声明

函数声明会在代码执行之前被解析和添加到变量环境中。这意味着即使函数在声明之前被调用,引擎也会能够找到它。

函数表达式声明

函数表达式是在代码执行时创建的。这意味着如果在声明之前调用了函数表达式,引擎将无法找到它,并会抛出一个错误。

示例

以下代码演示了函数声明式声明:

console.log(myFunction(1, 2));  // 输出:3

function myFunction(a, b) {
  return a + b;
}

以下代码演示了函数表达式声明:

console.log(myFunction(1, 2));  // 输出:Uncaught ReferenceError: myFunction is not defined

const myFunction = function(a, b) {
  return a + b;
};

结论

在 JavaScript 中,函数声明之所以可以在声明前被调用,是因为它们会在预编译阶段被解析并添加到变量环境中。这允许函数声明在代码执行之前被引用。另一方面,函数表达式是在代码执行时创建的,因此不能在声明前被调用。