# 大家好,我又回来了,继续整理一下面试中遇到的一些印象比较深的问题 #
# 记录问题,分享问题,希望能够帮助到各位 #
# 原本打算再这里也记录一下网络协议,想了想还是单独提出来去写可能会更好 #
一、防抖和节流
- 怎样理解防抖?
防抖的原理是,当事件触发后,只有再规定的时间段内没有再次触发,处理函数才会执行, 规定时间段内重复触发时,只会重置时间段的计时,再次检测是否有触发。
举个例子:有个需求是,当input输入框输入文字后,自动进行搜索,但是我们不可能在每输入一个字符时就去执行搜索,那么这里我们就可以引入防抖的概念去监听处理。 - 怎样理解节流?
节流的原理是,当事件触发以后,再规定的时间段内只会执行一个处理函数,即使在这个时间段内,事件被频繁的触发。
举个例子:我们在玩游戏时,英雄的普攻速度为0.75,意味着我们平A一下要花1.5秒,那么我们在这1.5秒内,无论平A键点的有多快,也无法在1.5秒内平A出第二下。
在这里,我想说的是,部分博客中举例说明中,节流可以用于按钮点击事件,用来防止按钮被用户频繁点击,导致事件被频繁触发。这里需要注意的是,我们应该在处理函数执行前去校验这里的处理是不是已经执行成功了,防止程序已经执行完了,但是事件又一次重复触发,预防后台隐形bug。 - 原理我知道了,我应该知道什么时候去使用呢?
我们不考虑代码逻辑,只关注页面视图的话,防抖和节流展示的效果很相似,可能会有人弄混淆。导致原理和名称牛头不对马嘴,或者实际开发中因为理解的偏差导致一些让使用者迷茫的问题。比如本来应该使用节流的做法,但是使用了防抖,那么就可能导致用户一直点击,但是就是不给反馈,一查才发现因为它一直在那个时间段内重复触发,一直都没有到处理函数那一步,就很尴尬了。
我在这里写下我自己的看法,仅供参考。我们需要它间隔一段时间后执行的,我们看防抖;我们需要它立刻执行,但是从开始执行到执行结束后的一段时间内,不让它二次执行的看节流。
二、跨域
- 为什么会跨域?
跨域产生的原因是由于游览器的同源策略,即当前页面的源和页面运行中加载的源不一致时,游览器出于安全考虑会对跨域的资源进行限制访问。 - 前端对于跨域的推荐处理操作?
(1) 配置跨域资源共享(CORS),它的原理是在服务端通过设置请求头(如 Access-Control-Allow-Origin)声明允许跨域访问的源。
优点:
标准化——W3C标准的解决方案,主流游览器全面支持(IE10+);
安全性可控——服务端可以精细控制允许的源、方法、头信息、Cookie等;
支持复杂请求——可处理预检请求,适用于非简单请求(如PUT、自定义头等);
缺点:
需服务端配合——前端无法独立解决(你要是会后端开发当我没说);
旧游览器兼容性——IE9以下需要降级方案(如XDomainRequest);
(2) 使用反向代理(前端代理),原理是通过同域服务器代理请求目标API,而绕过游览器同源策略。
优点:
无游览器兼容问题——无需前端参与;
隐藏真是API地址——保护后端服务信息,客户端获取不到真实地址;
灵活扩展——可附加缓存、负载均衡等
缺点:
服务器资源开销——需要维护代理服务器;
配置负责度——需要熟悉服务器配置;
注意:框架中的Proxy代理仅用于前端开发环境,是在本地开发服务器和目标API服务器中间添加了一个中间层来做转发。而这里的反向代理是需要独立的服务器来实现的
(3) JSONP(JSONP with Padding),原理是通过<script>标签的跨域特性,动态插入脚本获取数据。
优点:
兼容性好——支持所有老旧游览器
无需服务端大改——只需要返回函数包裹的JSON数据
缺点:
仅限GET请求——无法处理POST等复杂操作
安全隐患——易受XSS攻击,需严格校验请求来源
错误处理困难——无法通过http状态码捕获错误
(4) WebSocket,WebSocket协议天然支持跨域,服务端通过校验Origin头控制。
优点:
双向实时通信——适合聊天、实时推送等场景
安全性较高——服务端可主动校验Origin
缺点:
协议升级成本——需服务端支持WebSocket,不适合传统 REST API
(5) postMessage API,原理是通过window.postMessage实现跨窗口通信。
优点:
安全可控——需明确指定目标窗口的origin
灵活性高——支持任意数据类型
缺点:
仅限窗口间通信——不适用于普通API请求
需手动校验来源——存在恶意消息注入风险 - 还有哪些操作?为什么不推荐?只做了解,未深入发掘
(1)关闭游览器安全策略,通过启动参数禁用同源策略(如Chrome的--disable-web-security)
缺点:严重的安全隐患,生产环境杜绝使用
(2)document.domain,通过设置document.domain为相同父域名,实现子域间跨域
缺点:仅限同主域的时候;主域被攻击,所有子域都可能受影响;
(3)Flash插件,利用Flash的跨域策略文件
缺点:Flash已被淘汰,现代游览器已禁用
(4)图像 Ping(image Beacon),通过<img>标签发送GET请求
缺点:无法获取响应内容;数据大小有限制
三、缓存机制
-
什么是缓存?
游览器缓存是游览器将用户请求过的静态资源存储在本地磁盘或内存中,当用户再次访问同一资源时,直接从本地加载,而无需重新向服务器请求。 -
为什么需要缓存?
(1)提升性能
· 减少网络请求时间(本地加载速度会更快)
· 降低页面加载延迟,提升用户体验
(2)节省资源
· 减少服务器宽带消耗,降低服务器压力
· 节省用户流量
(3)应对弱网环境
· 在网络不稳定或无网络时,仍能加载已缓存资源 -
强缓存
· 工作原理:游览器检查资源的缓存过期时间,如果未过期,直接使用本地缓存,返回200;若过期则进入协商缓存阶段。
· HTTP 头部字段:
——Expires(HTTP/1.0):值是一个绝对时间,但是它依赖于客户端本地时间,可能因时区变化而导致缓存失效。
——Cache-Control(HTTP/1.1,优先级高于Expires)
————常用指令:
——————max-age=3600:资源有效期为3600秒
——————no-cache:强制使用协商缓存
——————禁止缓存
——————允许使用代理服务器缓存资源
——————仅允许游览器缓存资源
· 缓存位置
——Memory Cache:内存缓存(快速缓存,但关闭标签页后失效,适合小文件)
——Disk Cache:磁盘缓存(速度较慢,但持久化存储,适合大文件) -
协商缓存
· 工作原理:当强缓存失效后,游览器向服务器发送请求,并携带缓存标识
——如果资源未更新,服务器返回304,游览器使用本地缓存
——如果资源已更新,服务器返回200和新资源
· HTTP 头部字段:
——Last-Modified & if-Modified-Since
————服务器返回资源时,通过Last-Modified标记最后修改时间
————游览器下次请求时,携带if-Modified-Since字段(值为上一次的Last-Modified)
——缺点:精度只到秒级,毫秒级变化无法检测;文件内容未变但修改时间变化会导致缓存失效
——ETag & if-None-Match(优先级高于Last-Modified & if-Modified-Since)
————服务器返回资源时,生成唯一标识符ETag
————游览器下次请求时,携带if-None-Match字段(值为上一次的ETag )
——优点:精准判断内容变化 -
完整缓存流程
· 游览器请求资源
· 检查强缓存:未过期,使用本地缓存,完毕;过期,进入协商缓存,发起请求
· 向服务器发送请求,携带if-Modified-Since或if-None-Match
· 服务器检查资源是否更新:未更新,返回302,游览器使用本地缓存;已更新,返回200和资源,更新本地缓存。 -
补充Service Worker和HTTP/2,这个我也觉得单独写个文章比较好,所以这里简略
· 它们是现代Web性能优化和离线体验的核心技术
—Service Worker 是游览器背后的脚本,能拦截网络请求,实现完全离线的缓存控制
——生命周期:注册》安装》激活》拦截请求
——应用场景:无网络时;资源预加载;动态缓存
——限制:只能在HTTPS或localhost环境下运行;Service Worker文件本身的更新需要重新下载并激活(通过skipWaiting()强制生效)
—HTTP/2 通过多路复用、头部压缩、服务器推送等特性,优化了资源传输效率,间接提升了缓存的有效性
——多路复用:一个TCP连接并行传输多个资源,减少连接开销,加快资源加载
——服务器推送:服务器可以主动推送资源到游览器缓存(如css/js等)
——头部压缩:减少HTTP头部大小,降低网络开销(例如携带if-None-Match的请求更高效) -
总结:HTTP缓存是基础;Service Worker是增强,HTTP/2时传输优化
# 文章到这里就结束了,感谢各位的阅读,有问题欢迎评论区留言讨论
# 文章有错误,或者理解方向您觉得有问题,也欢迎评论区留言讨论,我会及时更新文章,避免误导,感谢