js闭包
1、概述
闭包值的是那些引用了另外一个函数作用域中变量的函数
2、特点
- 1、函数嵌套函数
- 2、内层函数可以访问外层函数的变量和参数
3、作用
- 1、防止变量和参数被垃圾回收机制回收(变量持久化)
- 2、防止变量和参数被外部污染(变量只能闭包内部可访问,实现私有化)
4、风险
滥用可能会造成内存泄露
5、闭包基本使用
不使用闭包
let i = 0;
function fun() {
i++;
console.log(`函数被调用了${i}次`);
}
// 下面是浏览器控制台操作
fun(); //输出 函数被调用了1次
fun(); //输出 函数被调用了2次
i = 1000;
fun(); //输出 函数被调用了1001次 (变量被修改了)
使用闭包
function fn() {
let i = 0;
return function() {
i++;
console.log(`函数被调用了${i}次`);
}
}
const fun = fn(); //fun()实际上调用的是方法里面返回的函数,并不会把变量i清空
// 下面是浏览器控制台操作
fun(); //输出 函数被调用了1次
fun(); //输出 函数被调用了2次
i = 1000;
fun(); //输出 函数被调用了3次
6、闭包使用场景
1、实现模块化
const myModule = (function () {
let count = 0;
function increment() {//加
count++;
}
function reset() {//清空
count = 0;
}
function getCount() {//获取count值
return count;
}
return {
increment,
reset,
getCount,
};
})();
myModule.increment();
console.log(myModule.getCount()); //输出 1
myModule.reset();
console.log(myModule.getCount()); //输出 0
2、封装私有化
function createPerson(name, age) {
let privateName = name;
let privateAge = age;
function getName() { //获取名字
return privateName;
}
function getAge() { //获取年龄
return privateAge;
}
function setName(newName) { //修改名字
privateName = newName;
}
function setAge(newAge) { //修改年龄
privateAge = newAge;
}
return {
getName,
getAge,
setName,
setAge,
};
}
const person = createPerson("张三", 20);
console.log(person.getName()); //张三
console.log(person.getAge()); //20
person.setName("李四");
person.setAge(25);
console.log(person.getName()); //李四
console.log(person.getAge()); //25
3、实现防抖和节流
<body>
<input type="text" placeholder="我是防抖" />
<button>我是节流</button>
<script>
function debounce(fn, wait) { //防抖
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, wait);
};
}
function throttle(fn, wait) { //节流
let isThrottled = false;
return function (...args) {
if (!isThrottled) {
isThrottled = true;
setTimeout(() => {
fn.apply(this, args);
isThrottled = false;
}, wait);
}
};
}
function handleInput() { //触发函数
console.log("触发了");
}
const debouncedHandleInput = debounce(handleInput, 1000);
const throttledHandleInput = throttle(handleInput, 1000);
document.querySelector("input").addEventListener("input", debouncedHandleInput);
document.querySelector("button").addEventListener("click", throttledHandleInput);
</script>
</body>