直接上题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//第一题:
for(var i = 0; i < 5; i++){
console.log(i);
}
//0, 1, 2, 3, 4
/*
不解释,很简单。
*/

//第二题
for(var i = 0; i< 5; i++){
setTimeout(function(){
console.log(i);
}, i * 1000)
}
//5, 5, 5, 5, 5
/*
最常见的考察作用域的题目,5个定时器,每个定时器内部的匿名函数引用着其所在作用域中的变量i,
等setTimeout内部的匿名函数开始执行时,匿名函数内部引用的变量i已经变成了5,所以输出的总是5
*/

for(var i = 0; i < 5; i++){
(function(i){
setTimeout(function(){
console.log(i);
}, i * 1000)
})(i);
}
//0, 1, 2, 3, 4
/*
循环中的5个声明即执行函数创建了5个各自独立的作用域环境,而且每个环境有着自己独立的i,
这个i作为参数从外界传过来(活动变量),所以,除非函数内部自己改变i,否则5个作用域中
的i值不会变化,会一直保持作为参数传入进来时候的值。setTimeout中的匿名函数处于对应的
作用域中,由于setTimeout中匿名函数一直引用着外层作用域中的变量i,所以外层作用域的i会
一直存在,当匿名函数执行的时候,便会输出各自所在作用域中的i值
*/

for(var i = 0; i < 5; i++){
(function(){
setTimeout(function(){
console.log(i);
}, i * 1000)
})(i);
}
//5, 5, 5, 5, 5
/*
这题和上一题的区别就是,循环中的声明即执行函数没有入参,所以,这5个声明即执行函数创建
的作用域中就不存在变量i。当setTimeout中匿名函数执行时,其会先在自己函数内部寻找变量i,
找不到则继续到各自所在外层作用域(声明即执行函数创建的作用域)中寻找i,这个时候依然找
不到,所以只能到全局环境中找了,全局环境中i已经变成了5,所以,结果就是一直输出5。
*/

for(var i = 0; i < 5; i++) {
setTimeout((function(){
console.log(i);
})(i), i*1000)
}
//立刻输出0,1,2,3,4
/*
setTimeout第一个参数的含义是,在指定延迟之后要执行函数。但是,题目中,第一个参数是一
个声明即执行函数。在执行代码时,js引擎在解析到第一个参数的时候直接把函数执行了,因为循
环是瞬间执行完的,所以控制台会立刻输出0,1,2,3,4。js引擎解析完成后,定时器中真正执行的代码如下:
setTimeout("0",0) 相当于 setTimeout(new Function("0"),0)
setTimeout("1",1000)
setTimeout("2",2000)
setTimeout("3",3000)
setTimeout("4",4000)
所以,在指定时间之后,控制台并不会输出什么东西。
*/