啥是函数声明

  1. function hexo () {
  2. // 函数体
  3. }

啥是函数表达式

  1. const hexo = function () {
  2. // 函数体
  3. }

区别

理解函数声明与函数表达式之间的区别,关键是理解提升
JavaScript 引擎在加载数据 时对它们是区别对待的。 JavaScript 引擎在任何代码执行之前, 会进行预编译。此时会发生函数声明提升,还有其他的提升,这里主要说的函数提升。 会先读取函数声明,并在执行上下文中 生成函数定义。而函数表达式必须等到代码执行到它那一行,才会在执行上下文中生成函数定义。

示例

函数声明提升

  1. // 没问题
  2. console.log(sum(10, 10));
  3. function sum(num1, num2) {
  4. return num1 + num2;
  5. }

以上代码可以正常运行,因为函数声明会在任何代码执行之前先被读取并添加到执行上下文。这个 过程叫作函数声明提升(function declaration hoisting)。在执行代码时,JavaScript 引擎会先执行一遍扫描, 把发现的函数声明提升到源代码树的顶部。因此即使函数定义出现在调用它们的代码之后,引擎也会把 函数声明提升到顶部

函数表达式

  1. // 会出错 TypeError: sum is not a function
  2. console.log(sum(10, 10));
  3. var sum = function(num1, num2) {
  4. return num1 + num2;
  5. };

以上代码会报错, 因为函数表达式不会进行函数提升,只有函数声明才会进行函数提升,var sum 会进行变量提升,但是它的初始值会为undefined的。sum(10,10) 此时sum = undefined 执行的话肯定会报错,当执行到第3条程序时,才会将sum赋值一个函数

如何正确的使用

理解函数声明与函数表达式之间的区别,关键是理解提升

示例

  1. // 千万别这样做!
  2. if (condition) {
  3. function sayHi() {
  4. console.log('Hi!');
  5. }
  6. } else {
  7. function sayHi() {
  8. console.log('Yo!');
  9. }
  10. }

这段代码看起来很正常,就是如果 condition 为 true,则使用第一个 sayHi()定义;否则,就 使用第二个。事实上,这种写法在 ECAMScript 中不是有效的语法。JavaScript 引擎会尝试将其纠正为适 当的声明。问题在于浏览器纠正这个问题的方式并不一致。多数浏览器会忽略 condition 直接返回第 二个声明。Firefox 会在 condition 为 true 时返回第一个声明。这种写法很危险,不要使用。不过, 如果把上面的函数声明换成函数表达式就没问题了:

  1. // 没问题
  2. let sayHi;
  3. if (condition) {
  4. sayHi = function() {
  5. console.log("Hi!");
  6. };
  7. } else {
  8. sayHi = function() {
  9. console.log("Yo!");
  10. };
  11. }