立即执行函数解决闭包问题
立即执行函数的定义
- 定义 : 此类的函数没有声明,在一次执行过后释放(被销毁),适合做初始化工作,针对初始化功能的函数,只想让他执行一次的函数,立即执行函数也有参数,也有返回值,也能预编译。
- 立即执行函数有两种写法
(function(){}()); w3c建议使用这一种
(function(){})();
补充:
- 只有表达式才能被执行符号执行
- 能被执行符号执行的表达式,这个函数的名字就会被自动忽略(放弃自己的名字)
- 能被执行符号执行的表达式基本上就是立即执行函数。
- 函数声明和函数表达式是两个东西,虽然都能定义函数。
- 一元正负号 + / -
+ function test(){}
// 加了正负号就是趋势上把他转换成数字了,也就是说转化成为表达式了,转化成表达式了就能被执行了,所以这样变成了立即执行函数
* / / 乘号和除号不行,&&,|| 前面放东西也可以
闭包问题
function test(){ //定义一个函数
var arr = []; // 定义一个空数组
for(var i=0; i < 10; i++){
//丰满空数组,让这个空数组添加十条数组,每一条都是一个function(){};
arr[i] = function(){
//随着for循环的i在变化,数组的i也在变,arr的每一次都等于一个全新的函数
document.write('i + " " ');
}
}
return arr;//把arr返回到外部
}
var myArr = test();
for(var j = 0; j < 10; j++){
//利用for 循环,分别执行十个函数体,函数里面定义了 document.write
//for循环是为了 打印这个数组,否则的话需要自己写很多次
//myArr[0]();
//myArr[1]();
myArr[j]();
}
- 首先上面的代码我们的初衷是想实现 打印出1 - 10 ;,可是我们打印出来的却是是个 十个10; 这就是闭包产生带来的后果,下面我们来分析一下产生闭包的原因和解决的办法
我们 第一个 var i = 0 的for循环 执行了10次,产生了10个彼此独立的函数,我们又把函数保存到了数组中,并且把数组return ,这样这十个函数与test一起产生了闭包。
既然产生了闭包,那么访问的test里面的变量,都是同一套,test产生了arr 和 i ,而这是个函数在外边要访问 i 变量 ,其实访问的都是同一个 i 。
为什么会打出10个十那,i 不是 < 10吗?
第一个 i= 0 , 当 i 转到 9 时候,执行 i++, 这时 i= 10 , 结束时 return arr ,返回 arr 。这十个 函数都是为了打印 i 的,那么在外部访问 i 的时候,i = 10,所以打印的都是10.
理解过程:在这个函数体中,当 arr[0] 时,document.write(i)的 i 是不变的,还是 i,
等函数保存到外部之后,等执行的时候,才会去找 i 的值。
这个赋值语句中,arr[0] = 函数;把一个函数体或者说是一个函数引用赋给数组的当前
位,数组的当前位需要马上被索取出来的(数组现在是当前第几位,我们是知道的,
因为这个是执行语句),当 for(var i = 0)时,arr[i]会变成 arr[0],但是这个 i 跟函数体
里面的 d.w(i+“”)里面的 i 是没有关系的,因为函数体 function(){}不是现在执行,
不会在意函数里面写的是什么,不是现在执行那么里面的 document.write 不会变成现
实的值,不是现在执行就是函数引用(函数引用就是被折叠起来的,系统不知道里
面写的是什么)
在执行 myArr[j]();的时候,系统才会读 document.write(i +””)里面的语句
在定义函数的时候是不看里面的,在执行的时候才看
如果我们想让这个函数打出来的是 0,1,2,3,4,5,6,7,8,9 ,那我们利用立即执行函数来解决这个问题。
function test (){
var arr = [];
for (var i = 0; i < 10; i ++){
(function (j) {
arr[j] = function () {
document.write( j + “ ”);
}
}(i));
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j ++){
myArr[j]();
}
理解过程:相当于在 for 循环里面有十个立即执行函数 function(j){}
在第一圈 i 是 0,j 也是 0,function(){document.write( j + “ ”)}拿着 j=0,进行循环
的第二圈 i 是 1,又有了一个新的 j 是 1,反复循环
形成了十个立即执行函数,有十个 j 对应
闭包的防范:闭包会导致多个执行函数共用一个公有变量,如果不是特殊需要,应尽量防止这种情况发生。