闭包
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
这里注意,内存泄漏并不是真正的泄露,而是指过多的占有资源导致可使用的资源变少
闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。
例如
function test1() {
var arr = [];
for (var i = 0; i < 10; i++){
arr[i] = function () {
document.write(i + " ");
}
}
return arr;
}
var myarr = test1();
for (var j = 0; j < 10; j++) {
myarr[j]();
}
//运行结果 10 10 10 10 10 10 10 10 10 10
为什么会出现这种情况?思考原因
原因其实就是在于在函数嵌套的过程中,内部函数被扔到了外面,生成了闭包,在函数真正执行时使用的i变量仍为test1函数中的变量,执行时i变量已执行完for循环变为10。
如何解决这种问题?就要使用到立即执行函数
立即执行函数
函数形式:小括号中 函数声明+执行符号
var num = (function (<参数>) {
var d = 0;
//函数体
return d;
}(参数值))
函数原理:
在JavaScript中有这样的语法规定:
只有表达式才能被执行符号执行,能被执行符号执行的函数,名字会被自动忽略
所以当函数声明被转换成表达式时就可以被执行并且忽略了名字
通过加号+ 非!等数学符号都可以将函数声明转化为表达式,当表达式被执行后,自动销毁。它的作用是针对初始化功能的函数
在上述程序中,立即执行函数是唯一的解
要想保存创建时的变量数据,可以通过闭包
function test2() {
var arr = [];
for (var i = 0; i < 10; i++){
(function (j){
arr[j] = function () {
document.write(j + " ");
}
}(i))
}
return arr;
}
var myarr = test1();
for (var j = 0; j < 10; j++) {
myarr[j]();
}
分析test2程序创建出的函数的作用域链
执行函数时执行document.write(j + " ")语句,
使用到的j为定义函数时立即执行函数传进来的j,因为生成闭包所以j被保存
当函数执行时,[[scope]]的为 0->函数自己的AO(关于AO见上一篇博客)
1->立即执行函数的AO
2->test1的AO
3->GO
因为for循环并不产生作用域,所以for循环中的j变量并不对函数造成影响。
所以在函数执行时,变量j取的是立即执行函数的AO中的j变量
前端小白,欢迎批评指正~