JavaScript中何时使用函数声明vs函数表达式?

Selective focus photography of yellow and orange post it notes on wall
Published on
/4 mins read/---

这篇文章只是我给开发者的一个快速笔记,用来帮助那些有时会忘记函数声明函数表达式这两个概念的开发者, 这样每次需要回顾的时候,他们可以直接来这里查看,而不用再去谷歌搜索

当然,那些每天使用JavaScript的开发者都会用以下语法写很多函数:

function doSomething() {} // 函数声明
 
// or
let doSomething = function () {} // 函数表达式
 
// or
let doSomething = () => {} // 函数表达式

第一种写法是函数声明,后面两种是函数表达式。 那么它们之间有什么区别,我们应该如何使用它们呢?

定义

第一个区别是如何定义一个函数

  • 函数声明使用function关键字声明,并且必须包含函数名称。
function doSomething() {}
  • 函数表达式的声明方式与函数声明类似,但是它被赋值给一个变量,并且只能通过该变量调用来执行。函数表达式中的函数名称可以省略(称为匿名函数)。
let doSomething = function () {}
 
// ES6语法中的匿名函数
let doSomething = () => {}

Hoisting

提升JavaScript的一种机制,它会在代码执行之前将函数变量提升到作用域的顶部。

Hoisting only applies to Function Declarations, not to Function Expressions.

可以通过以下例子简单理解:

sayHello() // => "Hello"
 
function sayHello() {
  console.log('Hello')
}

你可以在函数声明初始化的作用域内的任何位置调用它。

然而,函数表达式只能在定义之后才能被调用。

sayHello() // => Uncaught ReferenceError: Cannot access 'sayHello' before initialization
 
let sayHello = function () {
  console.log('Hello')
}

根据开发者的习惯以及项目或团队负责人制定的规则, 这两种定义函数的方式都可以使用。

不过,在某些特殊情况下,我们会使用函数表达式

IIFE

立即调用函数表达式,也就是在初始化后立即执行的匿名函数

;(function () {
  console.log('Code runs!')
})()
 
// ES6
;(() => {
  console.log('Code runs!')
})()

Callback

另一个使用函数表达式的场景是作为回调函数

buttonElement.addEventListener('click', function (e) {
  console.log('Button is clicked!')
})

or

array.map((item) => {
  // do stuff to an item
})

这是使用函数表达式的一个常见场景,因为我们不需要在整个作用域中都能访问到这个函数

总的来说,你可以灵活地使用这两种定义函数的方式。 如果你想要一个函数可以在作用域的多个地方灵活使用,就使用函数声明,如果你只是在特定场景短暂使用,就使用函数表达式

参考资料