在 JavaScript 语言里,主要有三种方式定义函数,分别是:函数声明,函数表达式和Function构造函数,下面依次介绍
函数声明(Function declaration)
1 | function person(name) { |
函数声明这是JavaScript最常见的函数定义法, function是函数声明关键词,person是函数名称标识符, 函数名之后的圆括号中是参数列表,参数之间使用逗号分隔,花括号是函数体
函数声明提升(hoisting), 函数声明的一个重要特性就是提升, 指的是整个函数体的提升, 也就是说可以在函数声明前调用函数。
函数声明重复
如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。1
2
3
4
5
6
7function add(x,y) {
return x+y;
}
function add(x,y,z) {
return n=x+y+z;
}
add(2, 3); // 结果是啥?
上面代码中,后一次的函数声明覆盖了前面一次。而且,由于函数名的提升,前一次声明在任何时候都是无效的,这一点要特别注意。
函数表达式(function expression)
1 | var person = function(name) { |
在 JavaScript 语言里, 函数也是对象,对象可以赋值给一个变量, 函数表达式是将一个匿名函数(anonymous function)赋值给一个变量,function关键词后面没有标识符
Function构造函数
1 | var person = new Function('name', 'console.log(name); return name;'); |
Function()构造函数可以传入任意数量的字符串实参,最后一个实参所表示的文本是函数体,可以包含任意数量的JavaScript语句。如果构造的函数不包含任何参数,则只需传入一个函数体即可。
与前两者方式不同的是,Function()构造函数允许JavaScript在运行时动态地创建并翻译函数。每次调用Function()构造函数都会解析函数体,并创建新的函数对象。因而,在循环或多次调用的函数中执行这个构造函数,执行效率会受影响。相比之下,循环中的嵌套函数和函数定义表达式则不会每次执行时都重新编译。
Function()构造函数还有值得注意的一点就是它所创建的函数并不是使用词法作用域,函数体代码的编译总在顶层函数执行。
1 | var name = 'up8'; // 顶层函数 |
我们可以将Function()构造函数认为是在全局作用域中执行的eval()。在实际编程中,Function()构造函数很少用到,前两中定义方法使用比较普遍。
return语句及其坑
在函数体内,遇到return,函数就执行完毕,并返回结果。如果没有 return ,函数执行完毕也会返回结果,只是返回的是undefined
我们要注意的是return有一个坑,在JavaScript中,有一个自动在行末添加分号的机制,看下面的示例:1
2
3
4function person() {
return {name: 'Felix Cao'};
}
person() // {name: 'Felix Cao'};
如果我们写成这样的话:1
2
3
4
5function person() {
return // 自动加了分好,相当于return undefined
{name: 'Felix Cao'}; // 因为上面已经返回,所以这句无法执行
}
person() // undefined
Reference
- Understanding delete — 这篇文章主要讲解JavaScript的delete操作符
- Different Ways of Defining Functions in JavaScript (This Is Madness!)