1

一、关于函数

JavaScript函数是指一个特定代码块,可能包含多条语句,可以通过名字来供其他语句调用以执行函数包含的代码语句。

比如我们有一个特定的功能需要三条语句实现

Example

那么每次想实现这个功能的时候就需要写这三句话,很麻烦,我们可以把这三条语句打包为一个函数

Example

这样每次想实现功能的时候我们就调用一下函数就可以了,调用函数通过函数名称()的形式调用

Example

二、声明方式

ECMA规范只明确了一点:函数声明必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符。

2.1 规则

(1)函数声明只能出现在 程序或函数体内。从句法上讲,它们不能出现在 Block(块)({ ... })中,例如不能出现在 if、while 或 for 语句中。因为 Block(块)中只能包含Statement语句, 而不能包含函数声明这样的源元素。

(2)另一方面,仔细看一看规则也会发现,唯一可能让表达式出现在Block(块)中情形,就是让它作为表达式语句的一部分。但是,规范明确规定了表达式语句不能以关键字function开头。而这实际上就是说,函数表达式同样也不能出现在Statement语句或Block(块)中(因为Block(块)就是由Statement语句构成的)。

三、函数声明(function 命令)

3.1 示例

函数声明

函数声明

上面的代码命名了一个job函数,以后使用job()这种形式,就可以调用相应的代码。这叫做函数的声明(Function Declaration)。

3.2 注意

(1)JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数。

(2)funcname是要声明的函数名称的标识符。函数名之后的圆括号中是参数列表,参数之间使用逗号分隔。当调用函数时,这些标识符则指代传入函数的实参

(3)function语句里的花括号必需的,这和while循环和其他一些语句所使用的语句块是不同的,即使函数体内只包含一条语句,仍然必须使用花括号将其括起来。

Example

四、函数表达式 (变量赋值)

4.1 定义

不以function开头的函数语句就是函数表达式。

4.2 匿名函数表达式

以表达式方式定义的函数,函数的名称是可选的,下面是匿名函数的一个例子,也就是函数没有名字

Example

这种形式看起来好像是常规的变量赋值语句,即创建一个函数并将它赋值给变量myFunction。这种情况下创建的函数叫做匿名函数。因为function关键字后面没有标识符

4.3 命名函数表达式

当然function命令后面也可带有函数名,下面是在定义时为函数命名的例子

Example

(1)命名函数表达式的好处是当我们遇到错误时,堆栈跟踪会显示函数名,容易寻找错误

(2)函数表达式其实是“忽略函数名称的,并且不可以使用函数名()这种形式调用函数。

Example

4.4 被括号括住的(function foo(){})

这种函数表达式不太常见,他是表达式的原因是因为括号 ()是一个分组操作符,它的内部只能包含表达式。

Example

4.5 注意

(1)函数表达式不会放到开头,所以不能在定义之前调用

Example

(2)若命名函数表达式(加上函数名),则函数名只在函数体内部有效,在函数体外部无效

Example

上面代码在函数表达式中,加入了函数名 x。这个 x 只在函数体内部可用,指代函数表达式本身,其他地方都不可用。这种写法的用处有两个,一是可以在函数体内部调用自身,二是方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)。

(3)下面的形式声明函数也非常常见。

Example

需要注意的是,函数的表达式需要在语句的结尾加上分号,表示语句结束。而函数的声明在结尾的大括号后面不用加分号。

五、函数声明和函数表达式的区别

5.1 说明

(1)如果不声明函数名称,他肯定是表达式。

(2)若声明了函数名称,可通过上下文来区分的,如果function test(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function test(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明

Example

(4)函数声明会在任何表达式被解析和求值之前先被解析和求值,即使你的声明在代码的最后一行,它也会在同作用域内第一个表达式之前被解析/求值。

Example

函数fn是在alert之后声明的,但是在alert执行的时候,fn已经有定义了。

(5)函数声明在条件语句内虽然可以用,但是没有被标准化,也就是说不同的环境可能有不同的执行结果,所以这样情况下,最好使用函数表达式。

Example

六、Function 构造函数

6.1 示例

(1)下面代码中,Function构造函数接受三个参数,除了最后一个参数是sum函数的“函数体”,其他参数都是add函数的参数

Example

(2)可以传递任意数量的参数给Function构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体

图片描述

6.2 注意

(1)Function构造函数无法指定函数名称,它创建的是一个匿名函数

(2)把Function的构造函数当作函数一样调用(不使用new操作符)的效果与作为Function的构造函数调用一样。

(3)从技术上讲,这是一个函数表达式。但不推荐使用,因为这种语法会导致解析两次代码。第一次是解析常规javascript代码,第二次解析传入构造函数中的字符串,影响性能。

图片描述

阅读更多

参考文章 深入理解JavaScript系列(2):揭秘命名函数表达式


WEBING
3.6k 声望6k 粉丝

GitHub [链接]