JS中函数主要分为声明式函数和赋值式函数

声明式函数

1
2
3
function 函数名 () {
函数体..
}

对于声明式函数来说,有函数的提升,并且函数名重复的话后面的会覆盖掉前面的,其实这也引出了js中的重载问题。。。这就是后话了。。(js中没有真正意义上的重载)

1
2
3
4
5
6
7
8
9
fn()
fn()
function fn () {
console.log(1);
}
function fn () {
console.log(2);
}
// 输出两次2

以下例子会输出什么结果呢?

1
2
3
4
5
6
7
8
9
10
console.log(a)
a()
var a = 3
function a () {
console.log(6)
}
console.log(a)
a = 7
console.log(a)
a()

输出的结果应该是这样的

1
2
3
4
5
6
7
8
9
10
console.log(a) // f a () { console.log(6) }
a() // 6
var a = 3
function a () {
console.log(6)
}
console.log(a) // 3
a = 7
console.log(a) // 7
a() // 报错,此时的a是一个变量,这儿当做函数使用,肯定报错啊

那么为什么会出现以上的结果呢?

首先我们要知道函数的提升和变量的提升,理论解释百度一大堆,这里用代码例子说明一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在上面的例子中定义了一个变量a,一个函数a
// 变量提升
var a
// 函数提升
function a () {
console.log(6)
}
// --------------
console.log(a) // 这儿为啥不输出undefined,却输出函数a呢?
// 在js中,如果变量名与函数同名,若变量没有赋值,则函数生效,否则变量生效

a() // 这儿输出6大家都明白,就不用解释了
// .....后面的代码很简单,就不说了

对于声明式函数,还有一个很有意思的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function fn () {
console.log(1)
};
(function () {
if (false) {
function fn () {
console.log(2)
}
}
fn()
})()
/*
这个代码在不同浏览器中得到的结果不一样
1. IE6~7 => 输出2
2. 低版本的火狐 => 输出1
3. 其他浏览器 => 报错
*/

赋值式函数

赋值式函数也叫函数表达式

不会出现函数提升的现象

1
2
3
4
5
fn() // 报错
var fn = function () {
console.log(1);
}
fn() // 1

但是有一个很有趣的现象

1
2
3
4
5
6
7
8
9
10
11
12
let fn = function f (n) {
f = n
console.log(typeof f); // function
return 1
}
console.log(fn()); // 1
console.log(f()); // 报错
/*
对于f有如下的特征:
1. 只读
2. 只能在函数内部访问,外部无法访问
*/