MDN:闭包是函数和声明该函数的词法环境的组合。
个人理解:父函数的子函数被父函数返回,无论什么时候他都可以访问父函数内的变量。(即使父函数被销毁)【解决了:作用域访问问题、变量可以一直保存】
ps:特点:
外部可以访问函数内部变量。
可以保存局部变量。
可以避免使用全局变量,防止全局变量污染。
(就是想用变量操作但只想要其中的一部分 还不想污染全局变量 就用闭包把其他变量用闭包隔离一下)
个人理解 求大佬指正 求泥络
ps:缺点:
内存泄漏 每运行一次父函数都会生成一个新的闭包。
其他人的理解口诀:
闭包找到的是同一地址中父级函数中对应变量最终的值。
很好的应用场景
二、防抖函数:
document.querySelector('input');
function debounce(func, time) {
// console.log(123123);
let timer = 0
return function (...arg) {
timer && clearTimeout(timer)
timer = setTimeout(() => {
timer = 0
func.apply(this, arg)
}, time)
}
}
input.onkeydown = debounce(function () { console.log(input.value) }, 500)
三、节流函数:
function throttle(func, time) {
let timer = 0
return function (...args) {
if (timer) return
func.apply(this, args)
timer = setTimeout(() => timer = 0, time)
}
}
二者区别:前者是讲最后一次执行后者是每隔一段时间执行一次
(一个将事件当成flag一个将时间固定下来当作flag)
四、用户点击问题
通常在外面设置一个flag,但是在Vue中就很麻烦要注册,污染全局作用域
如果用闭包就能很好的解决这个问题,来防止用户点击(发送过多的ajax请求 )
五、模块化封装(私有变量与公共接口/私有方法)
const counterModule = (() => {
let count = 0; // 私有变量
return {
increment: () => count++,
getCount: () => count
};
})();
counterModule.increment();
console.log(counterModule.getCount()); // 1(count 状态被保留)[1,7](@ref)
function createBankAccount(initialBalance) {
let balance = initialBalance; // 私有变量
return {
deposit: (amount) => balance += amount,
withdraw: (amount) => balance -= amount,
getBalance: () => balance
};
}
const account = createBankAccount(100);
account.withdraw(30);
console.log(account.getBalance()); // 70[4,8](@ref)
五、工厂函数
function createMultiplier(factor) {
return function(x) {
return x * factor; // 闭包捕获 factor
};
}
const double = createMultiplier(2);
console.log(double(5)); // 输出 10(factor=2 被保留)
我感觉闭包就是在我们日常敲码习以为常的用出来 不用太过纠结