概念 : 能够访问到 其他函数作用域中的对象的函数,称之为闭包。
常用 : 1. 回调函数 2.自调用函数 封装的私有方法 3.防抖 和 节流函数
回调函数 :
通常在 请求结束 拿到返回值的时候 使用 闭包。
function fun(success){
let returnData = { code : 200, msg : "success" , data : {} }
success(returnData)
}
fun(function (value) {
console.log(value)
})
此时 可以拿到 fun函数中的 returnData 值。
自调用函数 :
(如)单例模式 其中对象中的函数 就是闭包 add() value() 闭包的应用
var Counter = (function(){
var a = 10;
function changeBy(value){
a += value
}
return {
add : function(){
return changeBy(1)
},
value : function(){
return a;
}
}
})();
防抖 节流 :
/*
3.防抖 和 节流函数
*/
//防抖
function fd(fun,time){
let timer = null;
return function(){
if(timer !== null){
clearTimeout(timer)
}
timer = setTimeout(fun,time)
}
}
/* 节流 */
function jl(fun,time){
let timer = null;
return function(){
if(timer !== null){
return
}
timer = setTimeout(function(){
fun()
timer = null
},time)
}
}
练习题目:
// 面试题
function fn(){
var arr = []
for(var i = 0; i <10; i++){
arr[i] = function(){
return i
}
}
return arr
}
var arr = fn()
console.log(arr[0]())
题目 : console.log(arr[0]())的值?(答案 : 10)
解析 : arr中存储的 都是函数function(){ return i } 在 console 执行时 此时,因为 for中没有块作用域 a 的 值 等于 10。所有 等于 10
题目 2 : 如何 让 arr[0]() = 0 、 arr[1]() =1 …….
解析 :可以通过 闭包来实现 将 i 私有化
// 当 使用闭包 解决 (自调用函数 将i私有化)
function fnBb(){
var arr = []
for(var i = 0; i <10; i++){
// 通过 闭包(自调用函数) 来解决 作用域问题
(function(i){
arr[i] = function(){
return i
}
})(i)
}
return arr
}
闭包的弊端:
内存泄漏 : 闭包的链表已经创建,每一个闭包作用域携带一个指向大数组的间接的引用,造成严重的内存泄露。
解决方法 :
- 尽可能 不用
- 使用箭头函数 来控制 this指向
- let _this = this
- 手动 清空 null