(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中可能导致内存泄露。