JavaScript 函数与变量声明提升
函数作用域与变量提升
for
循环的例子:
javascript
// 打印:4、5、6
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(++i), 0)
}
// 打印:1、2、3
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(++i), 0)
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
变量声明在函数内部提升至顶部的例子:
javascript
var foo = 1;
function bar () {
if (!foo) {
var foo = 10;
}
alert(foo);
}
// 会 alert 10
bar();
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
变量声明提升在作用域最顶部,其次是函数声明,最后是赋值语句:
javascript
var a = 1;
function b () {
a = 10;
return;
function a() {}
}
b();
// 会 alert 1
alert(a);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
javascript
function a () {
var b = 1;
function b () {};
console.log(b);
}
// 输出 1
a();
1
2
3
4
5
6
7
2
3
4
5
6
7
javascript
function a () {
var b;
function b () {};
console.log(typeof b);
}
// 输出 'function'
a();
1
2
3
4
5
6
7
2
3
4
5
6
7
javascript
function a () {
function b () {};
var b;
console.log(typeof b);
}
// 也是输出 'function'
a();
1
2
3
4
5
6
7
2
3
4
5
6
7
javascript
function a () {
function b () {};
var b = 2;
console.log(b);
}
// 输出 2
a();
1
2
3
4
5
6
7
2
3
4
5
6
7
例子1
javascript
var msg = 'String A'
function test () {
// 弹出 `undefined`
alert(msg)
var msg = 'String A'
// 弹出 'String A'
alert(msg)
}
test()
// 上面的代码等价于下面的写法:
var msg = 'String A'
function test () {
var msg
alert(msg)
msg = 'String A'
alert(msg)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
来一个复杂的例子:
写出下面代码 a
、b
、c
三行的输出分别是什么?
javascript
// mark A
function fun (n, o) {
console.log(o)
return {
// mark B
fun: function (m) {
// mark C
return fun(m, n)
}
}
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
// 答案:
// undefined, 0, 0, 0
// undefined, 0, 1, 2
// undefined, 0, 1, 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
首先,可以分析得到的结论:标记 A 下面的 fun
函数和标记 C 下面 return
的 fun
是同一个函数,标记 B 下面的 fun
属性对应的函数不同于标记 A 和标记 C 下方的函数。下文为了行文方便,将各个标记处下方的函数方便叫做 A、B、C 函数。
a 行的分析:
a = fun(0)
:即a = fun (0) {console.log(undefined) return { // ... } }
,故输出undefined
;a.fun(1)
:相当于给 B 函数传了一个参数 1,返回了C
函数传参(1, 0)
执行后的结果,即 A 函数传参(1, 0)
后执行的结果,故输出 0;a.fun(2)
和a.fun(2)
同上,因为一开始a = fun(0)
已经将n
的值定为 0 了,后面console.log
出来的就都是0了;
b 行的分析:
fun(0)
:毫无疑问输出undefined
;fun(0).fun(1)
:参考 a 行的分析,可知这里输出的是 0;fun(0).fun(1).fun(2)
:类似的,输出 1;fun(0).fun(1).fun(2).fun(3)
:类似的,输出 2;
c 行的分析:
fun(0).fun(1)
:参见上面的分析,输出undefined
、0;c.fun(2)、c.fun(3)
:参见之前的分析,输出 1、1。