函数

函数是程序必不可少的组成部分之一,它允许我们创建可重用的代码单元。我们通常会将具有独立功能的代码提取成函数以提高代码的可重用性与可测试性。

JavaScript 中的函数是 “头等函数”,它具有以下特性:

  • 函数可以赋值给变量或对象属性。

  • 函数可以作为参数传递给另一个函数。

  • 函数可以作为函数返回值。

因为支持头等函数,所以 JavaScript 也在一定程度上支持函数式编程范式。接下来将概括介绍函数的使用方法。

函数声明

函数声明是最简单直接的函数定义方式。它的语法如下所示:

function name(param0, param1, ...) {
    body
}

函数声明由以下几部分组成:

  • 必须以 function 关键字开始。

  • 必须指定一个函数名,函数名应该是合法的标识符。

  • 由一对小括号包围的可选形式参数列表,参数可以有零或多个。

  • 由一对大括号包围的函数体。

函数表达式

除了函数声明外,还可以使用函数表达式来定义一个函数。函数表达式的语法与函数声明的语法有一个重要区别,那就是函数表达式中的函数名是可选的。当没有指定函数名时,该函数也叫作匿名函数。因为函数表达式属于表达式,并且表达式能够产生一个值,所以函数表达式能够产生一个值,该值是一个函数。函数表达式能够被应用在任何一处期待值的地方。例如,可以将函数表达式赋值给一个变量,也可以将函数表达式当作参数传递给其他函数。

立即执行的函数表达式

立即执行的函数表达式指的是在定义时就立即被调用的函数表达式。其常见的定义方式有以下两种:

;(function () {
    // ...
})();

// 或者

;(function () {
    // ...
}());

初看立即执行的函数表达式时可能会令人感到迷惑,尤其是包围函数表达式的一对小括号。这对小括号叫作分组运算符,常被使用在数学计算和逻辑表达式中。在分组运算符内部是一个表达式,将函数置于分组运算符之内时,该函数即成了函数表达式。若删除分组运算符,那么函数定义就成了函数声明,函数声明不允许被立即调用。实际上,分组运算符并非唯一能够将函数定义转换成函数表达式的运算符,例如,一元运算符也能完成这项工作。但综合来看,使用分组运算符是最优雅且副作用最小的选择。

在立即执行的函数表达式中,我们在起始和结尾位置分别添加了分号。这是为了防止使用代码压缩工具处理代码之后产生错误的语法。例如,将两个立即执行的函数表达式合并到一行并连接在一起后就可能出现错误。

立即执行的函数表达式有两个特点:其一是函数表达式和函数声明一样,都能够创建出新的作用域,在函数内部声明的变量不会对函数外部产生影响,因此提供了一定的数据封装性;其二是立即执行的函数表达式自身对外部作用域没有任何影响。在立即执行的函数表达式外部,无法通过函数表达式的函数名来访问它,而且在立即执行的函数表达式中,没有将函数引用赋值给任何外部变量。因此,立即执行的函数表达式与外界是孤立的。立即执行的函数表达式就好比创建的临时目录一样,我们可以在里面放置操作的临时文件,待操作完成后创建的临时目录和临时文件都会被清理掉,就好像没有出现过一样。

箭头函数

箭头函数是 ECMAScript 2015 中新增的特性,用来定义匿名的函数表达式。箭头函数一定是匿名函数。箭头函数最显著的特点是使用 “胖箭头” 符号连接函数的形式参数列表和函数体。箭头函数的基本语法如下所示:

(param0, param1, ...) => { body }

箭头函数除了能够提供简洁的语法外还有一个特别重要的特性,那就是箭头函数本身没有 this 绑定,它使用外层作用域中的 this 绑定。该特性能够帮助缓解程序中常见的一些错误。