浮点数精度
约 2607 字大约 9 分钟
2025-10-03
- 将浮点数转换成整数进行计算,再将结果转回浮点数。如果位数过长容易导致结果溢出
- 四舍五入
- 转换成字符串处理
- 使用成熟的库
Mutation Observer
强缓存适合静态资源
- 更新频率低:css、js、图片等上线后一般不会频繁变动,属于“内容稳定、体积较大、可复用性高”的资源
- 可控的“缓存更新机制”:强缓存会发生的问题是:资源更新后,旧缓存可能还在用。但前端工程一般会配合 文件指纹 hash 来解决,既保证 命中率高,又保证 更新及时。
- HTML一般变化频繁(比如新增功能、文案修改)所以适合协商缓存。如果html引用的静态资源发生改变那么对应的文件指纹hash也会改变,也就是html更改时对应静态资源更改会重新请求
进程、线程、协程的区别
进程
操作系统资源分配的基本单位。
- 有自己独立的内存空间(代码段、数据段、堆、栈)。
- 进程之间相互隔离,通信需要 IPC(管道、消息队列、共享内存)。
- 创建/销毁开销大。
线程
操作系统调度的基本单位。
- 属于进程的一部分,运行在进程里。
- 同一进程的多个线程共享内存(堆/全局变量),但有各自的栈。
- 切换开销比进程小。
- 可能有线程安全问题(需要锁)。
协程
用户态的“轻量级线程”,由程序自身控制调度。
- 不是操作系统调度,而是程序主动让出/切换。
- 更轻量,不需要内核态切换。
- 常用于异步编程、IO 密集场景。
- 需要程序员写逻辑来决定何时切换。
出现网络波动,如何确保数据传输,保证用户体验
前端
- 乐观更新:如用户点赞时先把点赞数加上,如果请求成功则不做处理,如果请求失败则回滚(将点赞数减去)并提示
- 重连
- 离线队列:将用户操作保存在队列中,当重连成功后再发送,如:聊天应用的重发消息
- 资源嗅探:将未处理完成的数据存储在indexedDB中,下次再进来再重传时先检查本地数据库中是否有数据,如果有可以直接拿出来使用
- ui占位:loading、骨架屏、占位图等
网络层
- 心跳:每隔一段时间发送一个心跳包检测连接是否断开,如果断开则重连
- 断点续传
后端
- 幂等接口:保证接口的设计不管操作多少次得到的结果都是一样的(post请求可能难以保证,可以加唯一标识配合校验机制)
- 数据库事务
defineProperty不支持新增属性的响应式,vue2如何处理的
- 使用
Vue.set
/this.$set
内部会使用defineReactive
为新属性设置 getter/setter。 - 对于数组的函数做劫持
nextTick
Vue 的响应式系统会异步更新DOM。当修改响应式数据时,Vue 并不会立即更新DOM,而是先在内存中记录变化,等本轮事件循环(microtask 或 next tick)结束后再统一渲染。 DOM 更新完成之后执行回调
好处:
- 避免重复渲染,提高性能。
- 批量处理多次数据更新,只渲染一次 DOM。
修改数据后立即想获取最新 DOM、执行动画或操作元素。
any、unknown、never
any
任意类型,关闭类型检查
- 可以赋值给任何类型
- 任何类型都可以赋值给
any
- 可以调用任意属性或方法,编译器不会报错
缺点:丧失类型安全,容易隐藏错误
unknown
未知类型,更安全的 any
- 可以赋值给
any
或unknown
类型 - 不能直接赋值给其他类型,必须先做类型缩窄(类型检查或类型断言)
优点:保留灵活性,同时保证类型安全
never永远不会出现的类型
- 用于永远不会有值的情况
- 常用于函数抛出异常或死循环
vue-router的生命周期
类型 | 钩子 | 特点 |
---|---|---|
组件内 | beforeRouteEnter | 进入前,无法访问 this |
组件内 | beforeRouteUpdate | 当前组件复用时,路由改变 |
组件内 | beforeRouteLeave | 离开组件前,可访问 this |
全局 | beforeEach | 全局前置守卫,可阻止导航 |
全局 | beforeResolve | 所有守卫及异步组件解析后执行 |
全局 | afterEach | 全局后置守卫,无法阻止导航 |
使用js实现不可变对象
- Object.freeze:将对象冻结,如果对象内部的属性有嵌套对象还需要递归冻结
- proxy拦截
握手阶段 | 非对称加密 | 安全交换对称密钥 |
---|---|---|
数据传输阶段 | 对称加密 | 高效加密 HTTP 数据 |
非对称加密 → 保证密钥安全 对称加密 → 保证传输性能
get和post的区别
对比点 | GET | POST |
---|---|---|
语义 | 获取数据 | 提交数据 |
参数位置 | URL 查询参数 | 请求体 |
长度限制 | 有 | 理论上无限制 |
缓存 | 可能缓存 | 默认不缓存 |
幂等性 | 是 | 否 |
安全性 | 参数暴露在 URL | 参数在 body,相对更安全 |
常见场景 | 查询、搜索 | 提交表单、上传文件 |
css实现三角形
原理:border 有宽度后,四角交接处会产生斜线,
<!--等腰三角形-->
<div class="w-0 h-0 border-100 border-solid border-transparent border-b-blue">
</div>
<!--直角三角形-->
<div class="w-0 h-0 border-100 border-solid border-transparent border-b-blue border-l-red">
</div>
<!--等边三角形-->
<div class="w-0 h-0 border-100 border-solid border-transparent border-b-blue border-b-180">
</div>
<!--等腰梯形-->
<div class="w-50 h-50 border-50 border-solid border-transparent border-b-120 border-b-blue">
</div>
块级作用域
es6之前没有块级作用域,所以在 for
或 if
中用 var
声明的变量,会“泄漏”到外层作用域。
使用立即执行函数模拟块级作用域
(funciton(){
var a=1
console.log(a)
})()
异步组件
解决按需加载的问题
底层实现其实就是利用 JavaScript 的动态 import()
+ Promise + Vue 的响应式渲染机制来实现的。
cdn
类型 | 说明 | 注意点 |
---|---|---|
静态资源 | JS、CSS、字体文件、图片、视频等 | 内容不经常改动,缓存友好 |
第三方库 | Vue、React、Lodash、jQuery 等 | 可以用官方 CDN,节省带宽 |
大文件/公用资源 | 公用图片、图标、logo 等 | 尽量去中心化,提升全球访问速度 |
不敏感内容 | 不包含用户隐私或安全信息 | CDN 一般是公共访问 |
路由的实现原理
- 监听 URL 变化
- 根据路由匹配组件
- 更新视图(Vue 渲染管线)
vue事件和原生事件的区别
对比点 | Vue 事件 | 原生事件 |
---|---|---|
绑定方式 | @ (v-on 指令) | addEventListener / onclick |
this 指向 | 组件实例(Vue 实例),可访问 data 、methods | 触发事件的 DOM 节点 |
修饰符 | 提供 .stop 、.prevent 、.once 等语法糖 | 需手动调用 event.preventDefault() 、stopPropagation() |
自定义事件 | 子组件可用 $emit 触发,父组件用 @xxx 监听 | 仅限于原生 DOM 事件 |
事件透传 | Vue2 用 .native ;Vue3 用 $attrs | 不存在这个概念 |
解绑方式 | Vue 会在组件销毁时自动解绑 | 需手动调用 removeEventListener |
nextTick原理
- 数据变化触发响应式系统:数据变化后对应的Watcher(观察者)会被通知
- 观察者入队列:vue内部维护一个观察者队列,同一个观察者再一个tick内只会更新一次(去重),多次数据变化会被合并
- nextTick回调队列:vue内部维护nextTick回调队列多次调用
nextTick
会合并回调。 - 微任务执行:先执行更新dom,再执行nextTick回调
统一代码规范
语言规范
- JavaScript/TypeScript:ESLint + Airbnb/Standard/自定义规则
- CSS/SCSS/LESS:Stylelint + 规范化命名(BEM/SMACSS/ITCSS)
- HTML/模板:格式化缩进、属性顺序、语义化标签 项目结构规范
- 约定目录结构、文件命名、组件命名规则
- 模块化方式:如 React/Vue/Angular 组件规范
- 统一资源管理:图片、icon、字体、样式等 编码习惯
- 缩进、分号、引号、行长度、空行规则
- 函数、变量、组件命名规则
- 注释规范:函数/类/接口文档化注释 Git 提交规范
- 使用 commit message 规范,如 Conventional Commits
- 分支策略:如 Git Flow、GitHub Flow
- PR 模板,要求描述功能、截图、测试方法
为什么读取元素的宽高信息也会导致重排
有些属性会强制浏览器先把最新的样式和布局计算出来再返回值。
事件中的target和currentTarget
- target:事件触发的实际元素
- currentTarget:事件监听器绑定的元素,当前正在处理事件的元素
js执行阻塞页面渲染
原因:浏览器无法预测js是否会修改dom或样式,所以必须在执行完js前暂停渲染保证渲染的一致性
Map和WeakMap
特性 | Map | WeakMap |
---|---|---|
键类型 | 任意类型 | 对象(弱引用) |
遍历能力 | 可遍历 | 不可遍历 |
size 属性 | 有 | 无 |
垃圾回收 | 键值存在Map的引用不回收 | 键对象无引用可回收,如果没有外部使用它就会自动被垃圾回收 |
常用场景 | 通用键值存储 | 私有数据/对象缓存/防内存泄漏 |
微任务递归生成微任务会陷入死循环吗
不会陷入真正的“死循环”,但它可能会导致浏览器或 Node.js 的事件循环被连续占用,造成可感知的“卡顿”或性能问题。
微任务是异步执行的不会像普通函数递归那样占用调用栈 但事件循环会被微任务队列持续占用,页面或应用无法响应其他任务队列中的任务
避免方案
- 限制递归深度
- 使用宏任务分隔
为什么transform不会导致重排
transform
属于复合图层(composite layer)属性,只会修改元素在渲染层的矩阵变换(位置、旋转、缩放、倾斜等),而不改变 DOM 布局信息。
贡献者
版权所有
版权归属:wynnsimon