(1)定义:
函数内部返回一个函数,返回出来的这个函数叫做被我们称之为闭包(个人理解的最简单的表现形式,)
(2)为什么要使用闭包呢?
局部变量在函数执行完之后就会被GC回收,有时候我们想在外部访问内部的变量,这个时候就用到了闭包
(3)闭包有两个作用:
a.访问函数内部的变量(函数作为返回值)
b.保存作用域(函数作为参数传递)
1 //1.访问函数内部的变量(函数作为返回值)
2 function test(){
3 var age = 18;
4 return function(){
5 console.log(age);
6 }
7 }
8
9 var myTest = test();
10 console.log(myTest);//为匿名函数,function(){console.log(age)}
11 myTest();//18
12
13
14
15 //另一个例子
16 function fn() {
17 var max = 10;
18 return function bar(x) {
19 if (x > max) {
20 console.log(x);
21 }
22 }
23 }
24 var f1 = fn();
25 console.log(f1);//function bar(x){if(x>max){console.log(x);}}
26 f1(15);//结果为15
27
28
29 //保存作用域(函数作为参数传递)
30
31 //保存作用域
32 function test(){
33 var a = 1;//局部变量
34 hehe = function(){//全局变量
35 a++;
36 };
37 return function(){
38 console.log(a);
39 }
40 }
41
42 var haha = test();//此时haha为test()执行完之后的返回值,匿名函数function(){consolloe.log(a)}
43 haha();//打印1
44 hehe();//hehe函数为全局变量,可以在外边执行,此处a++
45 haha();//打印2
46 hehe();//同上
47
48 //注意:haha为全局变量,不会被GC回收,所以test函数的返回值,一直存在,test的作用域一直存在,不会被GC回收
49
50 //注意:自由变量跨域取值时,要去创建这个函数的作用域取值,而不是“父作用域”;
51 //
52 var max = 10;
53 var fn = function(x){
54 if(x>max){
55 console.log(max);//10
56 console.log(x);//15
57 }
58 };
59
60 (function(f){
61 var max = 100;
62 f(15);
63 })(fn);
(4)闭包的使用
假设页面上有5个div节点,我们通过循环来给每个div绑定onclick事件,按照索引顺序,点击第一个div时弹出0,点击第2个div时弹出1,以此类推。
1 <body>
2 <div>1</div>
3 <div>2</div>
4 <div>3</div>
5 <div>4</div>
6 <div>5</div>
7 </body>
1 //闭包的使用
2
3 var nodes = document.getElementsByTagName('div');
4 for(var i=0;i<nodes.length;i++){
5 nodes[i].onclick = function(){
6 console.log(i);
7 }
8 }
9 //思考一下,存在什么问题??
10 // 点击每一个打印的都是5是不是···
11
12
13 var nodes = document.getElementsByTagName('div');
14 for(var i=0;i<nodes.length;i++){
15 (function(i){ //块级作用域或私有作用域
16 nodes[i].onclick = function(){
17 console.log(i);
18 }
19 })(i)
20 }
21 //上述方法优点:把每次循环的i值都封闭起来
(5)使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,
所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。