函数进阶
1. 函数防抖
在频率触发的情况下 只有等待一定的时间才会触发 执行一次代码
执行之前先清除之前的即将执行操作 保证只有最后一次生效
提高性能
防抖代码实现
// 使用setTimeout实现函数防抖
var t = null;
document.onmousemove = function ({
// 每次移动之前清除先前计时器
clearTimeout(t;
t = setTimeout(( => {
// 等待300毫秒后执行打印语句
console.log('鼠标移动停止300毫秒打印';
}, 300;
}
防抖应用场景
一些高频率事件 在被连续多次触发时 只需生效一次
搜索输入框 用户可能输入很快 在输入停止一段时间后再将请求发送
窗口大小时间resize 只需在窗口调整完成后再主席那个resize里代码 防止重复渲染 浪费性能
2. 函数节流
在频率触发的情况下 每间隔一段时间才触发一次
前一次存在触发执行未结束 后一次触发执行不会开始
提高性能
节流代码实现
// 利用 状态 概念
var t = null;
document.onmousemove = function ({
// 当计时器处于开启状态 不再重新开启新计时器
if(t return;
t = setTimeout(( => {
console.log("函数节流每300毫秒触发一次";
t = null;
}, 300;
}
节流应用场景
一些高频率事件 间隔一段时间运行一次 被连续多次触发如果处于间隔时间内无效
页面中的滚动事件
游戏中一些设计 如: 枪射速 每1000毫秒触发一次 每500毫秒触发一次
3. 闭包函数
有权访问另一个函数中的变量 并让函数不会因为执行完毕而被销毁
原理
让函数定义和表达式通过另一个函数return出来 这样在里面的函数就可以访问另一个函数内的变量 当外部函数被调用时就会返回一个内部函数
在函数内部可以访问到外部变量
- 避免全局变量命名空间的污染
- 延长变量生命周期
- 函数不会因为执行完毕而被销毁
闭包函数的创建
// 立即执行函数使fn得到return返回值
const fn = (function({
let a = 10;
return function({
return a;
}
}(
// fn返回值为函数 加上(调用函数得到此函数return值
console.log(fn(; // 10
闭包函数的应用
const divs = document.querySelectorAll("div";
// 添加了错误索引
for(var i = 0; i < divs.length; i++{
divs[i].onclick = function({
// 因为异步原因 执行点击事件时 i已经为最大值
console.log(i;
}
}
// 添加了正确索引
// 方法一
for(var i= 0; i < divs.length; i++{
;(function(i{
divs[i].onclick = function({
console.log(i;
}
}(i;
}
// 方法二
for(var i = 0; i < divs.length; i++{
divs[i].onclick = (function(i{
return function({
console.log(i;
}
}(i;
}
// 方法三
for(let i=0;i<divs.length;i++{
divs[i].onclick = function({
console.log(i;
}
}
沙箱模式
function outer( {
let a = 10;
let str = 'hello world';
// 返回一个对象
return {
// 对每个私有变量都准备两个函数:get用来获取,set用来修改
getA ( { return a },
setA (val { a = val },
getStr (val { return a },
setStr: function (val { a = val }
}
// 使用数据劫持中getter和setter优化
// return {
// get A( {return a}
// set A(val {a = val}
// get Str( {return str}
// set Str(val {str = val}
// }
}
4. 函数柯里化(Curring
将一次传入多个参数的函数 转换为多次执行 一次执行传入一个参数的函数
利用闭包延长变量生命周期把每次的传递参数保存下来 也可以保存每层function中程序
function fn1(a, b{
return a + b
}
function fn2(a {
return function (b {
return a + b
}
}
fn1(1, 2 // 3
fn2(1(2 // 3
// 解析
// fn2(1 返回function(b {return a + b} 并且这个返回的函数能访问到第一次传入的值1 并且 值1生命周期没有结束 fn2(1(2返回a + b = 3