函数执行形成一个不销毁的私有作用域(私有栈内存),是闭包
//闭包:柯理化函数
function fn(){
return function(){
}
}
var f = fn();
//闭包:惰性函数
var utils = (function(){
return {
}
})()
典型应用
(1)错误示范代码想实现点击某个tab,打印索引
//点击事件中,遇到i,i不是私有变量,像上一级作用域查找window,点击时,循环已经结束,i已经为最大值
for(var i = 0;i<tabList.length;i++){
tabList[i].onclick = function(){
console.log(i)
}
}
解决方案1,自定义属性存储i
for(var i = 0;i<tabList.length;i++){
//i循环时就已经赋值给myIndex,而不是异步执行点击事件时再去取已经循环结束的全局变量i
tabList[i].myIndex = i
tabList[i].onclick = function(){
console.log(this.myIndex)
}
}
解决方案2:闭包
for(var i = 0;i<tabList.length;i++){
//for循环阶段,onclick事件被赋值为--自执行函数的返回值,自执行函数堆地址被事件占用,所以私有作用域不释放,事件执行时,i为私有作用域的n,即每次循环的i值
tabList[i].onclick = (function(n){
var i = n;
return function(){
console.log(i)
}
})(i)
}
ES6的let存在块级作用域
for(let i = 0;i<tabList.length;i++){
tabList[i].onclick = function(){
//i为块级作用域的i,而不是作用域链中window中的i
console.log(i)
}
}
闭包的应用场景
这篇文章很好:闭包应用场景
结论:闭包找到的是同一地址中父级函数中对应变量最终的值