前言:JavaScript 中的函数是什么
一般来说,一个函数是可以通过外部代码调用的一个“子程序”。像程序本身一样,一个函数由称为函数体的一系列语句组成。值可以传递给一个函数,函数将返回一个值。
但在 JavaScript 中比较特殊的是,函数实际上也是一个对象。每个函数都是Function
类型的实例,所以和其他对象一样具有属性和方法,区别在于函数可以被调用。
一、函数定义
定义函数有多种方法,主要分为函数声明和函数表达式。
1.1 函数声明
function Identifier ( FormalParameterList ) { FunctionBody }
Identifier
:函数标识符(函数名)FormalParameterList
:参数列表FunctionBody
:函数体
1.2 函数表达式
(1)具名函数表达式
const myFunction = function Identifier ( FormalParameterList ) { FunctionBody }
(2)匿名函数表达式
const myFunction = function ( FormalParameterList ) { FunctionBody }
1.3 Function 构造函数
new Function (arg1, arg2, ... argN, functionBody)
arg1, arg2, ... argN
:函数使用零个或多个名称作为正式的参数名称。每一个必须是一个符合有效的JavaScript标识符规则的字符串或用逗号分隔的字符串列表functionBody
:一个构成的函数定义的,包含JavaScript声明语句的字符串。
注意:MDN官方不推荐使用
Function
构造函数创建函数,因为可能会影响JavaScript引擎优化。
1.4 箭头函数表达式
([param] [, param]) => { statements }
param => expression
param
:参数名称. 零参数需要用()表示. 只有一个参数时不需要括号. (例如foo => 1
)statements or expression
:多个声明statements需要用大括号括起来,而单个表达式时则不需要。表达式expression也是该函数的隐式返回值。
有关箭头函数后文详细介绍。
函数声明、函数表达式、Function构造函数的区别
假设我们要定义一个函数multiply
计算两个数的乘积,那么通过不同的方法定义如下:
// 函数声明
function multiplyDeclaration(x, y) {
return x * y;
} // 注意:函数声明结尾一般没有分号
// 匿名函数表达式
const multiplyAnonymousExpression = function (x, y) {
return x * y;
};
// 具名函数表达式
const multiplyNamedExpression = function funcName(x, y) {
return x * y;
};
// Function 构造函数
const multiplyFunctionConstructor = new Function('x', 'y', 'return x * y');
(1)函数声明提升
JavaScript引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。而函数表达式必须等到代码执行到它那一行时,才会在执行上下文中生成函数定义。
console.log(multiplyDeclaration(3, 7)); // 21
console.log(multiplyAnonymousExpression(3, 7)); // ReferenceError: Cannot access 'multiplyAnonymousExpression' before initialization
// 函数声明
function multiplyDeclaration(x, y) {
return x * y;
} // 注意:函数声明结尾一般没有分号
// 匿名函数表达式
const multiplyAnonymousExpression = function (x, y) {
return x * y;
};
可以看出,在函数声明之前调用该函数并不会出错,但是函数表达式会出现ReferenceError。
函数声明和函数表达式最大的区别在于:函数声明会提升
(2)性能问题
通过函数表达式定义的函数和通过函数声明定义的函数只会被解析一次,而Function构造函数定义的函数却不同。每次构造函数被调用,传递给Function构造函数的函数体字符串都要被解析一次 。 所以Function构造函数应尽可能地避免使用。
二、函数名称
函数名是指向函数的指针,可以通过 function.name
属性访问函数实例的名称。若函数没有名称,则会返回一个空字符串。 函数名称是不可写、不可迭代、可配置的属性,即{writable: false, enumerable: false, configurable: true}
(1)函数声明的名称
name
属性返回一个函数声明的名称。
function foo() {
}
console.log(foo.name);
(2)通过new Function()
创建的函数
使用new Function(...)
语法创建的函数,其名称为“anonymous”。
(new Function).name; // "anonymous&#