防抖
事件触发后,只有在规定的时间内没有再次触发,处理函数才会执行。如果在规定时间内事件再次触发,则重新计时。
防抖可以有效避免频繁触发事件时,执行过多无用的操作。
应用场景:
用户输入搜索框时:当用户停止输入一段时间后再发起搜索请求,防止每个输入都触发搜索操作。
浏览器窗口大小调整:用户停止调整浏览器窗口大小后再执行调整后的操作,防止窗口每次变化都触发大量重绘。
实现:
当事件被触发时,设置一个定时器。如果在定时器结束前再次触发事件,清除之前的定时器,重新设置新定时器。当定时器结束后,才执行回调函数。
function debounce(func, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};}
节流
保证一个函数在一定时间内只执行一次,即使在这段时间内事件被频繁触发。
节流可以限制函数的执行频率,适合那些需要定期执行的操作。
应用场景:
滚动事件:当用户滚动页面时,每隔一段时间触发一次回调,防止滚动时每次触发滚动事件都导致大量计算。
按钮点击事件:防止按钮被用户频繁点击,导致多次触发事件。
实现:
设置一个变量,事件触发后,变量设置为true,并开始计时,计时未结束期间的方法调用不触发事件,至计时结束,变量设置为false;
function throttle(func, limit) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false;
}, limit);
}
};}
浏览器缓存机制
浏览器为了提高网络请求速度,减少服务器请求,节省网络带宽,通常会把页面需要的部分资源如(js脚本,html文件,css、图片等静态资源)缓存在本地
缓存类型
内存缓存:存储速度最快,存储在计算机内存中,存储量小,浏览器关闭后清空
磁盘缓存:存储速度低于内存缓存,存储在硬盘中,存储量大,不会自动清空可以在浏览器设置中手动清空
应用缓存: 更高级的缓存机制主要用于离线应用,允许开发者指定哪些资源需要被缓存,以便用户在没有网络的情况下也能访问这些资源。应用缓存由HTML5引入,但已被Service Workers逐渐取代。
servers worker:
● 是一种运行在浏览器后台的脚本,通过 JavaScript 编程实现
● 是一种独立于页面的线程
● 可以拦截网络请求,并根据开发者定义的逻辑决定是使用缓存还是从网络获取资源
● 允许开发者在客户端实现复杂的缓存策略,例如离线支持、动态缓存更新等
● 开发者可以通过 JavaScript 完全控制缓存逻辑,包括缓存的内容、缓存的更新策略、请求的拦截等。
主要功能:
拦截网络请求:
Service Worker 可以拦截浏览器发出的所有网络请求(包括 HTML、CSS、JavaScript、图片等),并根据开发者定义的逻辑决定是直接从网络获取资源,还是从缓存中返回资源。
这种机制使得开发者可以实现复杂的缓存策略,例如:
缓存优先策略:先从缓存中查找资源,如果缓存中没有,则从网络获取并更新缓存。
网络优先策略:先尝试从网络获取资源,如果网络请求失败,则从缓存中返回资源。
自定义策略:根据资源类型、网络状况、用户行为等因素,动态调整缓存策略。
离线支持:
通过 Service Worker,开发者可以预先缓存一些关键资源(如 HTML 文件、CSS 文件、JavaScript 文件、图片等),使得用户即使在离线状态下也能访问网页的基本功能。
例如,一个新闻网站可以通过 Service Worker 缓存一些热门文章的页面,用户在离线时仍然可以阅读这些文章。
消息推送:
Service Worker 支持消息推送功能,即使用户没有打开网页,也可以通过推送通知向用户发送消息。这种功能常用于即时通讯应用、新闻推送、日程提醒等场景。
后台同步:
Service Worker 可以在后台同步数据,即使用户没有打开网页,也可以在设备联网时自动同步数据。
例如,一个待办事项应用可以在后台自动同步用户的待办事项数据。
应用场景
● 适用于需要高度定制化缓存策略的场景,例如离线支持、动态缓存更新、消息推送等。
● 适用于复杂的 Web 应用,如单页面应用(SPA)、离线应用等。
缓存类型策略 强缓存/协商缓存
● 适用于简单的静态资源缓存,例如图片、CSS 文件、JavaScript 文件等。
● 适用于大多数 Web 应用的静态内容优化。
● 开发者只能通过 HTTP 响应头设置缓存策略,浏览器会根据这些策略自动决定是否使用缓存。
强缓存
依赖 Cache-Control 和 Expires,直接使用本地缓存,无需与服务器通信。适合静态资源和长时间不变的文件。
它主要依赖于HTTP响应头中的Cache-Control和Expires字段。
Cache-Control:用于控制缓存的策略,例如max-age表示资源在本地缓存的有效时间。
Expires:表示资源的过期时间,是一个绝对时间戳。
如果资源在强缓存有效期内,浏览器会直接使用本地缓存,不会向服务器发送任何请求。
强缓存存储的数据
静态资源文件:如图片(.jpg、.png)、CSS 文件(.css)、JavaScript 文件(.js)等。这些文件通常在一段时间内不会改变,适合设置较长的强缓存时间。
HTML 文件:某些静态页面也可以设置强缓存,但需要谨慎,因为 HTML 文件内容可能会频繁更新。
字体文件:如 .woff、.ttf 等,这些文件通常不会频繁更新,适合强缓存。
协商缓存(Negotiated Cache)
协商缓存是当强缓存失效后,浏览器会向服务器发送请求,通过验证资源是否更新来决定是否使用本地缓存,依赖 Last-Modified 和 ETag,与服务器进行验证,适合动态内容和可能会更新的静态资源。
Last-Modified
这是一个时间戳,表示资源最后修改的时间。服务器会在响应头中返回 Last-Modified,浏览器在后续请求中会通过 If-Modified-Since 请求头将这个时间戳发送给服务器。如果服务器发现资源在这个时间戳之后没有被修改,就会返回 304 状态码,浏览器继续使用本地缓存。
ETag
这是一个唯一标识符,用于标识资源的版本。服务器会在响应头中返回 ETag,浏览器在后续请求中会通过 If-None-Match 请求头将这个标识符发送给服务器。如果服务器发现资源的 ETag 没有变化,就会返回 304 状态码。
协商缓存存储的数据
动态内容:如用户个人信息页面、新闻网站的新闻列表等。这些内容可能会频繁更新,但又不适合完全不缓存,因此适合使用协商缓存。
部分静态资源:对于一些可能会更新的静态资源(如某些配置文件),也可以使用协商缓存来减少不必要的数据传输。
【如果资源未被修改,服务器会返回304 Not Modified状态码,浏览器会使用本地缓存。
如果资源被修改,服务器会返回新的资源和200 OK状态码,浏览器会更新本地缓存。】
重绘
浏览器重新绘制页面的一部分或全部;相对轻量级,只改变元素的样式外观(颜色、背景、边框),不改变DOM元素的几何尺寸(宽、高、位置)。
例如:修改color、background、opacity样式
重排(回流)
浏览器重新计算DOM元素的几何尺寸、位置,并重新渲染页面及布局,相比重绘更加耗性能。
重排必会触发重绘,频繁重排会使页面卡顿。
例如:改变元素的 width、height、padding、margin、font-size 等样式。
改变元素的 display 属性。
添加、删除或修改 DOM 元素。
优化建议:
减少 DOM 操作,批量修改样式,使用虚拟 DOM,优化滚动和动画。
减少对元素几何尺寸的修改:
使用 transform 和 opacity 替代 top、left 等样式,因为 transform 和 opacity 不会触发重排。
赋值、拷贝
引用赋值:
a=b;
浅拷贝:
...{} ,Object.assign({},{})
深拷贝:
structuredClone
a= structuredClone (b);
性能更高,更广泛的数据类型支持,由现代浏览器提供的原生 JavaScript 方法,用于实现深拷贝,是作为 Web API 的一部分提供的,虽然可以通过 window.structuredClone 访问 structuredClone,但它本身并不是 Window 接口的一部分,而是一个独立的全局函数。
基于 HTML 标准中的结构化克隆算法,该算法最初是为了满足 Web Workers 中数据传输的需求而设计的,后来被整合到 Web API 中,成为浏览器原生支持的深拷贝方法
支持:
基础数据类型(字符串、数字、布尔值、null、undefined)。
对象和数组。
特殊对象类型(如; Date、Map、Set、RegExp 等)。
循环引用(能够正确处理循环引用)。
二进制数据类型(如 ArrayBuffer、Buffer 等)。
不支持:
● 函数:无法克隆函数。
● DOM 节点:无法克隆 DOM 元素。
● 属性描述符、getter 和 setter:不会保留这些元数据。
● 对象原型:不会保留原型链。
JSON.parse(JSON.stringify())
a= JSON.parse(JSON.stringify(b))
支持:
只能处理 JSON 兼容的数据类型,包括对象、数组、字符串、数字、布尔值、null
不支持:
● 函数 :会被忽略。undefined :会被忽略。
● 循环引用 :会报错。
● 特殊对象类型 :如 Date、RegExp、Map、Set、Buffer 等会被转换为普通对象或字符串。
手动编写function
函数、特殊引用数据类型(date、)等无法直接深拷贝需要通过手写函数循环️属性判断原型类型,新增对应类型数据用于接收被属性值返回的value信息。