闭包与立即执行函数
在看该文章之前呢,需要知道函数定义(包括函数声明和函数表达式两种方式)预编译,作用域链,执行期上下文,AO{},GO{}等知识。
1.什么情况下产生闭包
当内部函数保存到外部时,会生成闭包,闭包会导致原有作用域链不被释放,造成内存泄露(个人理解,内存没有被释放,可以用的内存变少,手里握住的沙子漏出去越来越少)。
2.产生泄露的案例
function test() {
var arr = [];
for(var i =0;i < 10;i++) {
arr = function() {
console.log(i);
}
}
return arr;
}
var myArr[] = test();
for(var j =0;j< 10;j++) {
myArr[j]();
}
上述图片中,在执行test()前生成了Go,AO。test函数执行完后,返回来arr数组赋值给了myArr数组,其中存放了10个Arr[i]function函数声明,test函数中并没有执行Arr[i]function函数,而是在后面全局的for循环语句中的myArrj中来执行Arr[i]函数,它的里面没有变量i,拿到的是test函数里面的Ao里面的i,当for循环语句循环完毕后,i==10.
所以最后打印出来的结果为10个10.
3. 如何解决
function test() {
var arr = [];
for(var i =0;i < 10;i++) {
(function (j) {
arr[j] = function () {
console.log(j);
}
}(i));
}
return arr;
}
var myArr = test();
for(var j =0;j< 10;j++) {
myArr[j]();
}
想要打印出来123456789,就是要把i变量和函数1对10的关系改成10对10的关系。这里使用立即执行函数。
(function (j) {
arr[j] =
}
}(i));
立即执行函数得到的结果是10个匿名函数声明,函数体里面的语句并没有执行。
4.拓展案例
这里if后面的条件判断语句中本来是一个函数声明,但是由于加了括号,所以变成了一个函数表达式,立即执行函数是一次性的,执行完就会被销毁,所以f==undefined;但是typeof比较特殊,可以识别undefind;将undefined转换成字符串“undefined”。然后答应出来的结果就变成了字符串1undefind。