├── CSS ├── @media.md ├── CSS3 新特性 & 可不可以继承的 CSS 属性.md ├── JPEG & PNG & GIF & SVG & WebP.md ├── display & visibility & opacity.md ├── flex & z-index.md ├── line-heigh 1.5 & 150%.md ├── margin 重叠.md ├── textarea 根据输入文字长度自动调整大小而不出现滚动条.md ├── transition & transform & animation & @keyframes & 红绿灯.md ├── translateX(-100px) & left -100px.md ├── 三点骰子布局.md ├── 两个 div 元素设置为 inline-block,它们间有 4px 间距.md ├── 单行文本隐藏 & 多行文本隐藏.md ├── 定位 & 盒模型 & BFC.md ├── 实现三个子盒子上中下排列 + 中间的高度自适应.md ├── 实现两列三行.md ├── 实现九宫格.md ├── 实现偶数列有背景颜色.md ├── 实现吸顶导航栏.md ├── 实现图片自适应容器.md ├── 实现垂直居中.md ├── 实现头部导航栏 + 内容区域 + 页脚的布局.md ├── 实现文本单行居中 + 多行靠左.md ├── 实现某元素宽 20 过渡为 40.md ├── 实现毛玻璃.md ├── 实现水平垂直居中.md ├── 实现水平居中.md ├── 实现第 1 个屏幕上下 2 种颜色 + 后面 N 个屏幕 1 种颜色.md ├── 实现雪碧图 & 精灵图.md ├── 左右固定中间自适应.md ├── 引入 CSS 的方式 & 解决样式冲突 & CSS 模块化 & 样式穿透 & CSS 解析选择器 & 权重 & 伪类 & 伪元素.md ├── 查找 div 下最后一个 p 标签.md ├── 清理浮动 & 解决高度塌陷.md ├── 画 0.5px 的线.md ├── 画圆 & 三角形 & 平行四边形 & 六边形 & 扇形.md ├── 画立方体.md ├── 获取全部非空 table 项.md └── 颜色表示方式.md ├── Computer Network ├── Access Token & Refresh Token.md ├── CDN & DNS.md ├── CORS & 二次预检.md ├── CSRF.md ├── Chrome HTTP1.1 同一域名最大 6 个并发连接.md ├── Cookie & Session.md ├── DNS host 文件配置错误.md ├── DOMContentLoaded & load & 浏览器对象 & 浏览器渲染 & 浏览器进程线程 & 浏览器图层 & 重绘回流 & V8.md ├── GET & POST.md ├── HTTP & HTTPS & HTTP1.1 & HTTP2 & HTTP3 & SSL & TLS 握手 & 数字签名 & 判断是否为长连接.md ├── HTTP 数据传输方式.md ├── HTTP 请求头 & 响应头.md ├── IPv4 & IPv6.md ├── Iframe.md ├── JWT.md ├── Last-Midified & Etag 局限性.md ├── MAC.md ├── OSI 七层模型.md ├── PM2.md ├── Ping.md ├── TCP & UDP │ ├── HTTP Keep-Alive & TCP keepalive.md │ ├── MTU.md │ ├── TCP & UDP 与 IP 交互 & 发送数据.md │ ├── TCP & UDP 共用端口.md │ ├── TCP & UDP.md │ ├── TCP 上的协议.md │ ├── TCP 传送数据过程中断电 & 崩溃.md │ ├── TCP 保证可靠性.md │ ├── TCP 头的标志位.md │ ├── TCP 报文组成.md │ ├── TIME_WAIT.md │ ├── UDP 数据包大小.md │ ├── 三次握手的原因.md │ ├── 为什么有了 TCP 还要用 UDP 实现一个可靠性传输.md │ ├── 半连接 & 全连接.md │ ├── 四次挥手的原因.md │ ├── 数据从发送到接收的拷贝次数.md │ ├── 查看 TCP 占用内存情况.md │ ├── 第四次挥手若客户端 kill.md │ ├── 粘包.md │ └── 限制 TCP 最大连接数.md ├── WebSocket & Web Worker & Service Worker.md ├── XSS.md ├── localStorage & sessionStorage & 检测 localStorage 存储溢出.md ├── preload & prefetch.md ├── token 失效.md ├── 三次握手四次挥手.md ├── 前后端交互.md ├── 前端缓存 & 资源更新问题.md ├── 反向代理.md ├── 多端适配.md ├── 密码登录.md ├── 强缓存 & 协商缓存.md ├── 扫码登录.md ├── 本地 hosts 文件.md ├── 检测设备机型 & 检测桌面浏览器和移动浏览器.md ├── 浏览器兼容.md ├── 清除浏览器缓存并删除 token,如何保持登录状态?.md ├── 状态码.md ├── 离线包.md ├── 跨域方式.md ├── 跨域设置 Cookie.md ├── 输入 URL 到页面展示的全过程.md └── 鉴权.md ├── Data Structure ├── Array.prototype.sort.md ├── DFS & BFS.md ├── 二叉搜索树 & 平衡二叉树.md ├── 判断有向图是否存在环.md ├── 十大排序时空复杂度.md ├── 哈希冲突.md ├── 堆 & 栈.md ├── 拓扑排序.md ├── 时间复杂度 & 空间复杂度.md ├── 树 & 图.md ├── 稳定 & 不稳定.md ├── 红黑树 & B 树 & B+ 树.md ├── 链表 & 数组.md └── 队列.md ├── Front-End Engineering ├── JS 错误检测.md ├── Tree-Shaking & 代码分割.md ├── WebView & JSBridge.md ├── Webpack & Vite.md ├── git fetch & git pull & git merge & git rebase & git revert & git reset & git stash & 版本回滚 & 解决冲突.md ├── loader & plugin & import & require & esm & commonjs & pnpm & npm & module & chunk & bundle.md ├── require 原理 & 在浏览器中执行.md ├── 两个 JavaScript 文件循环引用.md ├── 内存泄漏检测.md ├── 前端工程化.md ├── 微信小程序.md ├── 执行 npm run dev 到页面展示的全过程.md ├── 把静态资源打包为同一 Bundle.md └── 白屏检测.md ├── HTML ├── Attribute & Property.md ├── Canvas.md ├── HTML5 新特性.md ├── alt & title.md ├── src & href.md ├── 自定义属性.md ├── 行内元素 & 块级元素.md └── 语义化.md ├── JS(practical aspects) ├── AJAX.md ├── Array.prototype.fill.md ├── Array.prototype.flat.md ├── Array.prototype.flatMap.md ├── Array.prototype.forEach & map & filter.md ├── Array.prototype.includes.md ├── Array.prototype.push & unshift.md ├── Array.prototype.reduce.md ├── Array.prototype.reverse.md ├── ArrayReader.md ├── DOM to JSON.md ├── DOM 节点查找.md ├── Event.Bus.md ├── JSON to DOM.md ├── JSON.parse.md ├── JSON.stringify.md ├── JSONP.md ├── Map & Set.md ├── O(n)时间查找数组排序后的最大差值.md ├── Object.assign.md ├── Object.create.md ├── Object.freeze.md ├── Object.is.md ├── Promise A+.md ├── Promise.all.md ├── Promise.allSettled.md ├── Promise.any.md ├── Promise.race.md ├── String.prototype.includes.md ├── String.prototype.repeat.md ├── String.prototype.trim.md ├── Virtual DOM && Render && Diff && Patch.md ├── Vue Router.md ├── Vuex.md ├── apply & call & bind.md ├── async & await.md ├── compose.md ├── curry.md ├── debounce & throttle.md ├── findDuplicate.md ├── instanceof.md ├── isString.md ├── lazyMan.md ├── localStorage 存储数据.md ├── lodash.get.md ├── mergePromise.md ├── new.md ├── requestAddition.md ├── setTimeout 实现 setInterval.md ├── sleep.md ├── tic-tac-toe.md ├── todoList & 拖拽.md ├── util.promisify.md ├── v-model.md ├── 一次 setState 一次更新.md ├── 三进制转十进制.md ├── 上传文件.md ├── 下拉刷新 & 单选 & 全选.md ├── 两数之和最大的所有组合数.md ├── 串行 pipeline.md ├── 串行网络请求.md ├── 事件冒泡和事件捕获阶段的点击事件弹窗.md ├── 事件委托.md ├── 二分查找.md ├── 倒计时.md ├── 函数缓存.md ├── 分红包.md ├── 列表单选 & 多选 & 取消选择.md ├── 判断对象是否为空.md ├── 判断数组是否为等差数列.md ├── 判断数组是否含重复值.md ├── 判断数组里各天的微信步数是否满足传入时间范围内的微信步数.md ├── 判断点是否在矩形内.md ├── 十大排序.md ├── 千分位转化.md ├── 单例模式.md ├── 原生路由.md ├── 合并对象.md ├── 合法 URL.md ├── 后端返回的对象数组属性名转换.md ├── 后端返回的对象数组根据 date 重排.md ├── 图片懒加载.md ├── 大数相加.md ├── 字符串转小写后按字典序并去重.md ├── 字符串转嵌套对象.md ├── 定时器.md ├── 寄生组合式继承.md ├── 对象拍平.md ├── 对象数组重叠区间.md ├── 对象转换为路径数组.md ├── 并发限制 Scheduler.md ├── 弹窗.md ├── 微信红包.md ├── 快速幂.md ├── 找出两个数组或对象数组中不共有的元素.md ├── 找到毒药的最少次数.md ├── 抖音移动端界面和刷视频功能.md ├── 数组乱序.md ├── 数组元素奇前偶后.md ├── 数组去重.md ├── 数组对象转换.md ├── 数组转换为对象.md ├── 数组转树.md ├── 日期格式化.md ├── 日期转化:一年第几天.md ├── 时间地区转换.md ├── 时间格式化输出.md ├── 有向连通图.md ├── 构造小于给定数的最大数.md ├── 查找 24 小时制时间列表中最小时间差.md ├── 栈.md ├── 树的 DFS & BFS.md ├── 树转数组.md ├── 根据给定字符串获取对象属性值.md ├── 检测数组是否有序.md ├── 模板引擎.md ├── 汉字数字转整数.md ├── 浅拷贝 & 深拷贝 & lodash.cloneDeep.md ├── 深度比较.md ├── 瀑布流.md ├── 牛顿法求根号 n.md ├── 生成区间 (left, rigth) 的 n 个不重复的数字.md ├── 登录页面.md ├── 短横线与驼峰转化.md ├── 系统内存占用.md ├── 红绿灯.md ├── 给定字符串, 找出所有长度 Num 的重复子串.md ├── 统计所有 url 中每天访问的 url.md ├── 翻转字符串中的每个单词.md ├── 自定义 React Hook.md ├── 荷兰国旗问题.md ├── 观察者模式.md ├── 解决回调地狱.md ├── 解析 URL 的查询字符串为对象.md ├── 解析依赖顺序.md ├── 计算器.md ├── 计算异步函数执行时间.md ├── 请求 5s 内无结果则提示超时.md ├── 请求失败重试.md ├── 调用一次函数获取下一质数.md ├── 路由导航主页 & 详情页.md ├── 轮播图.md ├── 递增数组格式化输出.md ├── 链式调用 add 函数.md ├── 链式调用实现加减乘除.md ├── 闭包实现计数器.md ├── 隔 1 秒输出 1,持续输出至隔 10 秒输出 10.md ├── 隔 s 秒执行一次,共执行 n 次.md └── 颜色字符串转换.md ├── JS(theoretical aspects) ├── Array & Object & Map & Set & WeakMap & WeakSet.md ├── BOM & DOM.md ├── ES6 & ES7.md ├── Generator & Async & Await.md ├── JS 单线程.md ├── JS 设计模式及原则.md ├── MutationObserver.md ├── NaN && === && ==.md ├── Promise.md ├── TS 与类型体操.md ├── TS 书写类型强制 & 非强制字段.md ├── TS 以属性值来为类型.md ├── TS 内置工具类型.md ├── TS 枚举.md ├── TS 装饰器.md ├── TS 设置只读.md ├── TypeScript.md ├── apply & call & bind.md ├── async & defer.md ├── for of & for in & Object.keys & forEach & map & 就地改变数组 & 返回新数组.md ├── null & undefined.md ├── requestAnimationFrame & requestIdleCallback.md ├── this & 箭头函数 & new & 类数组.md ├── var & let & const & 定义全局变量 & 变量提升 & 函数提升.md ├── 事件冒泡 & 事件捕获 & 事件委托 & window.addEventListener & event.target & event.currentTarget.md ├── 事件循环.md ├── 作用域.md ├── 判断两个 JavaScript 对象是否相等.md ├── 判断数据类型 & 判断数组.md ├── 原型 & 原型链 & 创建无原型的对象.md ├── 原生 JavaScript & 前端框架.md ├── 取消请求 & Axios 函数对象 & 拦截器 & AJAX.md ├── 可以继承的方法.md ├── 垃圾回收机制.md ├── 异步编程.md ├── 数据类型 & 值传递 & 引用传递 & 0.1 + 0.2 & 018 - 017 & 隐式类型转换.md ├── 数组增删改查的方法.md ├── 数组遍历的方法.md ├── 触发事件 & 添加事件.md ├── 闭包.md └── 面向过程 & 面向对象.md ├── LICENSE ├── My Interview ├── Aurora System 一面(OC).md ├── CSDN 一面(26min 过).md ├── Momenta 二面(67min 挂).md ├── Momenta 一面(61min 过).md ├── PatSnap 一面(62min OC).md ├── Pony.AI 一面(45min 挂).md ├── RightCaptial 一面(43min 挂).md ├── TCL 一面(20min 挂).md ├── VAST 一面(65 min 过).md ├── YY 一面(44min 挂).md ├── eBay 一面(44min 挂).md ├── 三维家(61min OC).md ├── 三维家(90min 挂).md ├── 亿迅科技(64min OC).md ├── 同程旅行一面(55min OC).md ├── 哈啰出行一面(40min 过).md ├── 哈啰出行二面(42min OC).md ├── 商汤科技一面(72min 过).md ├── 商汤科技二面(52min 过).md ├── 字节 Data AML 一面 & 二面 & 三面(挂).md ├── 字节 Tiktok 国际化广告一二面(HR 面挂).md ├── 字节抖音直播一面(挂).md ├── 字节飞书一面(72min 挂).md ├── 实在智能一面(20min 过).md ├── 实在智能二面(48min OC).md ├── 小米一面(67min 过).md ├── 小米二面(76min OC).md ├── 小红书一面(68min 挂).md ├── 小红书一面(72min).md ├── 小鹅通(53min 挂).md ├── 帆软一面(75min OC).md ├── 得物青训一面(27min OC).md ├── 微信公众号一面 & 微信小店一面.md ├── 快手商业化一面(61min 挂).md ├── 快手效率工程一面(69min 过).md ├── 快手效率工程二面(59min 挂).md ├── 恒生电子一面(25min 挂).md ├── 有乐今天一二面(95min OC).md ├── 海康威视一面(11min 挂).md ├── 海康威视一面(69min OC).md ├── 清华课题组(20min OC).md ├── 滴滴一面(49min 过).md ├── 滴滴网约车一面 & 二面(OC).md ├── 玄武云一面(88min OC).md ├── 百度二面(70min 挂).md ├── 科大讯飞一面(54min OC).md ├── 科大讯飞一面(58min 挂).md ├── 经纬恒润一面(68min OC).md ├── 网易云音乐一面(50min OC).md ├── 网易传媒一面(46min 过).md ├── 网易传媒二面(67min OC).md ├── 美团到店一面(挂).md ├── 美团商户保险一面(76min).md ├── 美团平台一面(44min 挂).md ├── 美的一面(61min OC).md ├── 英视睿达一面(30min OC).md ├── 蔚来一面(87min 挂).md ├── 蔚来供应链一面(69min 挂).md ├── 货拉拉一面(76min 过).md ├── 趣链科技(55min 过).md ├── 钛动科技一面(55min 挂).md └── 高顿一面(56min).md ├── Node.js ├── Express & Koa.md ├── Nest.js 生命周期 & 装饰器.md ├── Next.js 布局 & 路由 & 获取及更新数据 & CSR & SSR & SSG & ISR.md ├── 代理参数校验.md ├── 创建进程.md ├── 同步 & 异步方法.md ├── 处理高并发.md ├── 实现容灾.md ├── 封装接口.md ├── 执行类似 DOM 操作.md ├── 模块.md ├── 模块化.md ├── 流式读取 & 直接读取.md └── 错误处理.md ├── OS ├── 内存调度 & 磁盘调度算法.md ├── 死锁.md ├── 物理内存 & 虚拟内存.md ├── 状态机.md ├── 线程同步机制.md ├── 进程 & 线程.md ├── 进程切换.md ├── 进程管理.md ├── 进程调度算法 & CPU 调度.md ├── 进程间通信.md └── 银行家算法.md ├── README.md ├── React ├── Fiber & 调度过程.md ├── JSX & React.createElement & React.cloneElement.md ├── React Native.md ├── React router │ ├── history & hash.md │ ├── react-router-dom.md │ ├── 动态路由.md │ ├── 路由的原理.md │ └── 路由的配置.md ├── React 的性能优化.md ├── React-Redux.md ├── React17 & React18.md ├── Redux.md ├── State & Props.md ├── react-dom 包.md ├── 不可变数据.md ├── 事件机制.md ├── 单向数据流 & 双向数据绑定.md ├── 受控组件 & 非受控组件.md ├── 在函数组件中调用子组件中的方法 & 暴露子组件数据给父组件.md ├── 生命周期.md ├── 类组件 & 函数组件.md └── 组件通信.md ├── Vue ├── CSS scoped.md ├── MVC & MVVM.md ├── Vue & React.md ├── Vue Router.md ├── Vue2 & Vue3.md ├── Vuex.md ├── data 返回函数.md ├── keep-alive.md ├── key.md ├── method & computed & watch & watchEffect.md ├── ref & reactive.md ├── v-if & v-show & v-for & v-model.md ├── 全局组件 & defineComponent & mixin.md ├── 插槽全家桶.md ├── 模板编译.md ├── 父子组件通信 & 父组件调用子组件的方法.md ├── 生命周期钩子 & 其他钩子 & $nextTick.md ├── 自定义指令.md └── 访问数据的优先级.md └── type-challenge ├── Absolute.md ├── Append Argument.md ├── Append to object.md ├── Capitalize.md ├── Chainable Options.md ├── Deep Readonly.md ├── Diff.md ├── First of Array.md ├── Flatten.md ├── If.md ├── Includes.md ├── KebabCase.md ├── Last of Array.md ├── Length of String.md ├── Merge.md ├── Permutation.md ├── Pop.md ├── Promise.all.md ├── Push.md ├── Replace.md ├── ReplaceAll.md ├── String to Union.md ├── Trim Left.md ├── Trim.md ├── Tuple to Union.md ├── Type Lookup.md ├── Unshift.md ├── concat.md ├── 元组转换为对象.md ├── 获取元组长度.md └── 获取函数参数类型.md /CSS/@media.md: -------------------------------------------------------------------------------- 1 | 1. 屏幕宽高 `width` 和 `height`:`@media (min-width: 600px) { ... }` 2 | 2. 设备宽高 `device-width` 和 `device-height`:`@media (min-device-width: 800px) { ... }` 3 | 3. 方向 `orientation`:`@media (orientation: landscape) { ... }` 4 | 4. 纵横比 `aspect-ratio`:`@media (aspect-ratio: 16/9) { ... }` 5 | 5. 分辨率 `resolution`:`@media (min-resolution: 2dppx) { ... }` 6 | 6. 颜色 `color`:`@media (min-color: 2) { ... }` 7 | 7. 打印 `print`:`@media print { ... }` 8 | -------------------------------------------------------------------------------- /CSS/JPEG & PNG & GIF & SVG & WebP.md: -------------------------------------------------------------------------------- 1 | WebP 图片大小比 JPEG 或 PNG 小,但其压缩和解压缩过程更为复杂,浏览器解析 WebP 图片需更多的计算工作,因此在快网环境下其加载和渲染时间不如 JPEG 或 PNG 文件 2 | 3 | 1. Joint Photographic Experts Group:通过离散余弦变换和量化技术进行压缩,适用于需压缩以减少大小的彩色自然场景图片,传输大量图片,但有损压缩,不支持透明背景 4 | 2. Portable Network Graphics:通过 DEFLATE 压缩算法进行压缩,适用于 Logo 和高质量透明背景图片,无损压缩,支持透明背景,但不适合传输大量图片 5 | 3. Graphics Interchange Format:通过 Lempel-Ziv-Welch 压缩算法进行压缩,轻量级,无损压缩,支持动画,但支持 256 种颜色 6 | 4. Scalable Vector Graphics:基于 XML 的矢量图片格式,适用于 Logo 和动画,轻量级,无损压缩,支持无限缩放 7 | 5. WebP:通过 VP8 视频编码和 Riff 文件容器技术进行压缩,轻量级,无损压缩,支持动画和透明背景,压缩效率高于 JPEG 和 PNG,但兼容性较差,通过 HTML5 `picture` 指定多个源图片,浏览器选择其支持的首个图片格式加载 8 | 9 | -------------------------------------------------------------------------------- /CSS/display & visibility & opacity.md: -------------------------------------------------------------------------------- 1 | `display: none`:元素及其子元素从 Render Object 树中移除,不占据页面空间也不参与页面布局,隐藏元素时触发回流,同时由于其不存在于渲染树中,元素的 JavaScript 事件无法被触发 2 | `visibility: hidden`:元素及其子元素均不可见但仍存在于 Render Object 树中,占据页面空间并参与页面布局,隐藏元素时触发重绘,同时由于其仍存在于渲染树中,元素仍响应绑定的 JavaScript 事件程序 3 | `opacity: 0`:元素及其子元素均不可见但仍存在于 Render Object 树中,占据页面空间并参与页面布局,隐藏元素时触发重绘,同时由于其仍存在于渲染树中,元素仍响应绑定的 JavaScript 事件程序,此外 `opacity: 0` 还创建独立于默认文档流的复合图层 4 | -------------------------------------------------------------------------------- /CSS/line-heigh 1.5 & 150%.md: -------------------------------------------------------------------------------- 1 | `line-height: 1.5` 基于当前元素的 `font-size` 计算,随当前字体自动缩放,子元素继承比例系数,根据自身的 `font-size` 动态计算 2 | `line-height: 150%` 基于父元素的 `font-size` 计算,子元素父元素计算后的固定像素值 3 | 4 | ```css 5 | .parent { 6 |   font-size: 16px; 7 |   line-height: 1.5; 8 |   /* 16px * 1.5 = 24px */ 9 | } 10 | 11 | .child { 12 |   font-size: 14px; 13 |   /* 14px * 1.5 = 21px */ 14 | } 15 | 16 | .parent { 17 |   font-size: 16px; 18 |   line-height: 150%; 19 |   /* 16px * 150% = 24px */ 20 | } 21 | 22 | .child { 23 |   font-size: 14px; 24 |   /* 24px */ 25 | } 26 | ``` -------------------------------------------------------------------------------- /CSS/margin 重叠.md: -------------------------------------------------------------------------------- 1 | margin 重叠是指在某些情况下,两个垂直方向上相邻的块级元素之间的 `margin` 不会相加,而是选择其中的一个最大值作为实际的 `margin` 2 | 3 | 1. 相邻兄弟元素的 margin 重叠:如果两个块级元素相邻,且没有任何内容,也没有 padding、border 将它们分开,它们的垂直 `margin` 将重叠 4 | 5 | ```CSS 6 |
Element A
7 |
Element B
8 | ``` 9 | 10 | 在上面的例子中,两个 div 元素之间的实际 `margin` 将是 30px(取两者中的较大值),而不是 50px 11 | 12 | 2. 父元素与第一个或最后一个子元素的 margin 重叠:如果一个块级元素没有顶部边框、顶部内边距,那么它的顶部 `margin` 和它的第一个子元素的顶部 `margin` 之间会发生重叠。同样的,如果它没有底部边框、底部内边距,它的底部 `margin` 和它的最后一个子元素的底部 `margin` 也会发生重叠 13 | 14 | 3. 空块级元素的 margin 重叠:如果在一个块级元素中没有边框、内边距、高度、最小高度、最大高度限制,且它没有内联内容,那么该元素的顶部和底部 `margin` 将重叠 15 | 16 | ###### 解决方案 17 | 18 | 1. 使用 `padding` 或 `border` 为元素添加边框或内边距 19 | 2. 使元素浮动 `float: left/right` 20 | 3. 触发 BFC,如设置 `overflow: auto/hidden` 创建一个新的 BFC 21 | 4. 使用 Flexbox 或 Grid 布局 22 | 5. 在两个元素之间添加一个 `display: inline-block` 的空 div 23 | -------------------------------------------------------------------------------- /CSS/textarea 根据输入文字长度自动调整大小而不出现滚动条.md: -------------------------------------------------------------------------------- 1 | ```html 2 | 3 | 4 | 5 |     6 |     7 |     textarea 8 | 9 | 10 |     11 |     19 | 20 | 21 | ``` -------------------------------------------------------------------------------- /CSS/translateX(-100px) & left -100px.md: -------------------------------------------------------------------------------- 1 | `translateX` 利用 GPU 加速,动画平滑,对 CPU 负担小,减少重绘和回流的次数,移动元素时,元素仍占据原来空间但不影响文档流中其他元素的布局,仅仅只是在视觉上移动元素 2 | 改变定位元素的 `left` 属性直接影响其在文档流中的位置,若为 `position: absolute;` 的元素,其脱离文档流,若为 `position: relative;` 的元素仍占据原来空间,仅仅只是在视觉上移动元素,对 CPU 负担大,导致重绘和回流 3 | -------------------------------------------------------------------------------- /CSS/两个 div 元素设置为 inline-block,它们间有 4px 间距.md: -------------------------------------------------------------------------------- 1 | 当两个 `div` 元素设置为 `inline-block` 时,它们间有 4px 的间距,因为 `inline-block` 元素间的空白字符在 HTML 中基于 HTML 的空白符合并规则被渲染成一个空格,该空格在渲染时产生额外间距 2 | 3 | 1. 移除 HTML 中的空白字符,确保 `inline-block` 元素在 HTML 代码中无空格、换行或制表符分隔 4 | 5 | ```html 6 |
7 | ``` 8 | 9 | 2. 在元素间添加 HTML 注释阻止空白字符渲染 10 | 11 | ```html 12 |
13 | ``` 14 | 15 | 3. 为第二元素设置负的 `margin` 值抵消间距 16 | 17 | ```css 18 | div + div { 19 | margin-left: -4px; 20 | } 21 | ``` 22 | 23 | 4. 父元素设置 `font-size: 0;`,重新为 `inline-block` 元素指定 `font-size` 24 | 25 | ```css 26 | .container { 27 | font-size: 0; 28 | } 29 | .container div { 30 | font-size: 16px; 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /CSS/单行文本隐藏 & 多行文本隐藏.md: -------------------------------------------------------------------------------- 1 | ```js 2 | .single-line { 3 |   overflow: hidden; 4 |   text-overflow: ellipsis; 5 |   white-space: nowrap; 6 |   width: 200px; 7 | } 8 | 9 | .multi-line { 10 |   overflow: hidden; 11 |   text-overflow: ellipsis; 12 |   display: -webkit-box; 13 |   -webkit-box-orient: vertical; 14 |   -webkit-box-clamp: 3; 15 | } 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /CSS/实现三个子盒子上中下排列 + 中间的高度自适应.md: -------------------------------------------------------------------------------- 1 | ```HTML 2 | 3 | 4 | 5 |     6 |     7 |     Box 8 |     21 | 22 | 23 |    
24 |        
Top
25 |        
Middle
26 |        
Bottom
27 |    
28 | 29 | 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /CSS/实现九宫格.md: -------------------------------------------------------------------------------- 1 | `index.html` 2 | 3 | ```HTML 4 | 5 | 6 | 7 |     8 |     9 |     9 10 |     21 | 22 | 23 |    
24 |        
1
25 |        
2
26 |        
3
27 |        
4
28 |        
5
29 |        
6
30 |        
7
31 |        
8
32 |        
9
33 |    
34 | 35 | 36 | ``` 37 | 38 | ###### grid 39 | 40 | ```CSS 41 | .container { 42 |     display: grid; 43 |     grid-template-columns: repeat(3, 1fr); 44 | } 45 | 46 | .cell { 47 |     border: 1px solid #000; 48 |     aspect-ratio: 1 / 1; 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /CSS/实现偶数列有背景颜色.md: -------------------------------------------------------------------------------- 1 | ```CSS 2 | ul li:nth-child(even) { 3 |     background-color: red; 4 | } 5 | ``` -------------------------------------------------------------------------------- /CSS/实现吸顶导航栏.md: -------------------------------------------------------------------------------- 1 | ```CSS 2 | 3 | 4 | 5 |     6 |     7 |     Sticky-header 8 |     21 | 22 | 23 |     24 |    
content
25 | 26 | 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /CSS/实现图片自适应容器.md: -------------------------------------------------------------------------------- 1 | 1. `max-width` + `height: auto` 2 | 3 | ```CSS 4 | img { 5 | max-width: 100%; 6 | height: auto; 7 | } 8 | ``` 9 | 10 | 2. `object-fit` 11 | 12 | ```CSS 13 | img { 14 | width: 100%; 15 | height: 100%; 16 | object-fit: cover; 17 | } 18 | ``` -------------------------------------------------------------------------------- /CSS/实现头部导航栏 + 内容区域 + 页脚的布局.md: -------------------------------------------------------------------------------- 1 | ```HTML 2 | 3 | 4 | 5 |     6 |     7 |     Container 8 |     22 | 23 | 24 |    
25 |        
header
26 |        
main
27 |         28 |    
29 | 30 | 31 | ``` -------------------------------------------------------------------------------- /CSS/实现文本单行居中 + 多行靠左.md: -------------------------------------------------------------------------------- 1 | ```HTML 2 | 3 | 4 | 5 |     6 |     7 |     Text Align 8 |     22 | 23 | 24 |    
25 |         单行文本居中显示 26 |    
27 |    
28 |         第一行文本靠左显示 29 |         第二行文本靠左显示 30 |    
31 | 32 | 33 | ``` -------------------------------------------------------------------------------- /CSS/实现某元素宽 20 过渡为 40.md: -------------------------------------------------------------------------------- 1 | ```HTML 2 | 3 | 4 | 5 |     6 |     7 |     Transition 8 |     20 | 21 | 22 |    
23 | 24 | 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /CSS/实现毛玻璃.md: -------------------------------------------------------------------------------- 1 | Frosted Glass 效果依赖于 `backdrop-filter` 属性,它用于对元素背后区域应用样式,如模糊或颜色偏移 2 | 3 | ```CSS 4 | .frosted-glass { 5 | backdrop-filter: blur(10px); 6 | background-color: rgba(255, 255, 255, 0.5); 7 | } 8 | ``` 9 | 10 | 11 | -------------------------------------------------------------------------------- /CSS/实现第 1 个屏幕上下 2 种颜色 + 后面 N 个屏幕 1 种颜色.md: -------------------------------------------------------------------------------- 1 | ```HTML 2 | 3 | 4 | 5 |     6 |     7 |     Screen color 8 |     36 | 37 | 38 |    
39 |        
40 |        
41 |    
42 |    
43 |    
44 |    
45 | 46 | 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /CSS/左右固定中间自适应.md: -------------------------------------------------------------------------------- 1 | 1. Flex 2 | 3 | ```css 4 | .parent { 5 |     display: flex; 6 | } 7 | 8 | .left, 9 | .right { 10 |     width: 100px; 11 | } 12 | 13 | .center { 14 |     flex-grow: 1; 15 | } 16 | ``` 17 | 18 | 2. Grid 19 | 20 | ```css 21 | .parent { 22 |     display: grid; 23 |     grid-template-columns: 100px 1fr 100px; 24 | } 25 | 26 | .left, 27 | .right { 28 |     width: 100px; 29 | } 30 | 31 | .center { 32 |     width: 100%; 33 | } 34 | ``` 35 | 36 | 3. 定位 37 | 38 | ```css 39 | .parent { 40 |     position: relative; 41 |     height: 100vh; 42 | } 43 | 44 | .left, 45 | .right { 46 |     position: absolute; 47 |     top: 0; 48 |     bottom: 0; 49 |     width: 100px; 50 | } 51 | 52 | .left { 53 |     left: 0; 54 | } 55 | 56 | .right { 57 |     right: 0; 58 | } 59 | 60 | .center { 61 |     margin-left: 100px; 62 |     margin-right: 100px; 63 | } 64 | ``` 65 | 66 | 4. calc 67 | 68 | ```css 69 | .parent { 70 |     width: 100%; 71 | } 72 | 73 | .left, 74 | .right { 75 |     width: 100px; 76 |     display: inline-block; 77 | } 78 | 79 | .center { 80 |     width: calc(100% - 200px); 81 | } 82 | ``` -------------------------------------------------------------------------------- /CSS/查找 div 下最后一个 p 标签.md: -------------------------------------------------------------------------------- 1 | 1. `querySelector`:只能找作为最后一个子元素的 `p` 标签,若 `div` 的最后一个子元素不是 `p` 标签,这种方法失效 2 | 3 | ```js 4 | const lastP = document.querySelector("div > p:last-child"); 5 | ``` 6 | 7 | 2. `lastElementChild` 8 | 9 | ```js 10 | const pTags = document.querySelector("div").getElementsByTagName("p") 11 | const lastP = pTags[pTags.length - 1]; 12 | ``` 13 | 14 | 3. `querySelectorAll` 15 | 16 | ```js 17 | const allP = document.querySelectorAll("div > p"); 18 | const lastP = allP[allP.length - 1]; 19 | ``` -------------------------------------------------------------------------------- /CSS/画 0.5px 的线.md: -------------------------------------------------------------------------------- 1 | 1. `transform` 缩放 2 | 3 | ```html 4 | 5 | 6 | 7 |     8 |     9 |     0.5px 10 |     17 | 18 | 19 |    
20 | 21 | 22 | ``` 23 | 24 | 2. `border` 25 | 26 | ```css 27 | .half-pixel-line { 28 | height: 0; 29 | border-top: 0.5px solid black; 30 | } 31 | ``` 32 | 33 | 3. `background-image` 34 | 35 | ```css 36 | .half-pixel-line { 37 | height: 1px; 38 | background-image: linear-gradient(to right, black 50%, transparent 50%); 39 | } 40 | ``` -------------------------------------------------------------------------------- /CSS/画圆 & 三角形 & 平行四边形 & 六边形 & 扇形.md: -------------------------------------------------------------------------------- 1 | ```css 2 | .cycle { 3 |     width: 100px; 4 |     height: 100px; 5 |     border-radius: 50%; 6 |     background-color: blue; 7 | } 8 | ``` 9 | 10 | ```css 11 | .triangle { 12 |     width: 0; 13 |     height: 0; 14 |     border-left: 50px solid transparent; /* 左侧边框透明 */ 15 |     border-right: 50px solid transparent; /* 右侧边框透明 */ 16 |     border-bottom: 86.6px solid blue; /* 底部边框颜色设置,高度为边长的一半乘以根号3 */ 17 | } 18 | ``` 19 | 20 | ```css 21 | .parallelogaram { 22 |     width: 100px; 23 |     height: 100px; 24 |     background-color: blue; 25 |     transform: skewX(-20deg) translateX(50px); /* X轴倾斜,负值向左倾斜,并向右移动 */ 26 | } 27 | ``` 28 | 29 | ```css 30 | .hexgon { 31 |   width: 100px; 32 |   height: 100px; 33 |   background-color: blue; 34 |   clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); 35 | } 36 | ``` 37 | 38 | ```css 39 | .sector { 40 |     width: 100px; 41 |     height: 100px; 42 |     border-radius: 50%; 43 |     background: conic-gradient(black 0deg 90deg, transparent 90deg); 44 |   } 45 | ``` 46 | -------------------------------------------------------------------------------- /CSS/获取全部非空 table 项.md: -------------------------------------------------------------------------------- 1 | 非空 `` 至少包含一个 ``,且该 `` 至少包含一个 `
` 或 ``,该 `` 或 `` 包含非空白内容 2 | 3 | ```js 4 | const getNoEmptyTables = () => { 5 |   const tables = document.querySelectorAll("table"); 6 |   const noEmptyTables = Array.from(tables).filter((table) => { 7 |     const trs = table.querySelectorAll("tr"); 8 |     return Array.from(trs).some((tr) => { 9 |       const cells = tr.querySelectorAll("td, th"); 10 |       return Array.from(cells).some((cell) => cell.textContent.trim() !== ""); 11 |     }); 12 |   }); 13 |   return noEmptyTables; 14 | }; 15 | 16 | const noEmptyTables = getNoEmptyTables(); 17 | console.log(noEmptyTables); 18 | ``` 19 | 20 | ![[1712416976748.png]] -------------------------------------------------------------------------------- /CSS/颜色表示方式.md: -------------------------------------------------------------------------------- 1 | ```css 2 | .color { 3 |     color: red; 4 |     color: #FF0000; 5 |     color: rgb(255, 0, 0); 6 |     color: rgba(255, 0, 0, 0.5); 7 | } 8 | ``` 9 | 10 | RGBA:Red + Green + Blue + Alpha 接受四参数:红绿蓝值 0-255 和 Alpha 值 0-1,0 完全透明,1 完全不透明 11 | HEX:`#` + 6 位十六进制数,前两位代表红,中两位代表绿,后两位代表蓝,转换时,从 HEX 的十六进制数值中提取相应红绿蓝三色的十六进制值,将其转换为十进制数值,再结合给定 Alpha 值,通过 `rgba` 函数生成最终的颜色字符串 12 | 13 | ```JavaScript 14 | const hexToRgba = (hex, alpha = 1) => { 15 |   let r = 0, 16 |     g = 0, 17 |     b = 0; 18 |   if (hex.length === 4) { 19 |     r = parseInt(hex[1] + hex[1], 16); 20 |     g = parseInt(hex[2] + hex[2], 16); 21 |     b = parseInt(hex[3] + hex[3], 16); 22 |   } else if (hex.length === 7) { 23 |     r = parseInt(hex[1] + hex[2], 16); 24 |     g = parseInt(hex[3] + hex[4], 16); 25 |     b = parseInt(hex[5] + hex[6], 16); 26 |   } 27 |   return `rgba(${r}, ${g}, ${b}, ${alpha})`; 28 | }; 29 | ``` 30 | -------------------------------------------------------------------------------- /Computer Network/Access Token & Refresh Token.md: -------------------------------------------------------------------------------- 1 | Access Token:用于访问受保护的资源如 API,客户端在有效期内可用其认证状态和访问权限,其具有较短的有效期,风险相对较低,即便被泄露,攻击者也只能在短时间内使用它 2 | Refresh Token:用于在 Access Token 过期后获取一个新的 Access Token,无需用户再次登录,Refresh Token 有更长的有效期,其安全性比 Access Token 高,因为它只用于与认证服务端通信,而不是直接用来访问受保护的资源 3 | 4 | 1. 用户首次登录时,基于 OAuth 2.0 或 OpenID Connect 的认证服务端在认证用户后,同时发送 Access Token 和 Refresh Token 给客户端 5 | 2. 客户端使用 Access Token 访问受保护资源,若有效,则请求成功,若无效或过期,则使用 Refresh Token 来获取一个新的 Access Token,认证服务端验证 Refresh Token 的有效性,若验证成功,发送新的 Access Token 6 | 3. 客户端使用新的 Access Token 访问受保护资源,直到 Access Token 再次过期,若 Refresh Token 也过期,用户需重新登录 7 | -------------------------------------------------------------------------------- /Computer Network/CDN & DNS.md: -------------------------------------------------------------------------------- 1 | Content Delivery Network 是基于 DNS 协议实现的一种分布式网络,它使用边缘计算原理,通过在各地部署多个节点服务端,将网站内容分发到距离用户最近的节点,从而更快更可靠地将内容发送给用户 2 | 3 | - CDN 提供商在全球范围内的多个地点部署节点服务端,这些节点缓存源服务端上的内容 4 | - 当用户请求一个通过 CDN 服务加速的网站或资源时,该请求首先到达 DNS 服务器,DNS 解析系统解析并返回最接近用户且负载较低的 CDN 节点的 IP 地址,即负载均衡 5 | - 用户请求被重定向到所选的 CDN 节点,用户从该节点获取内容,该节点看起来就像用户的本地服务器,若请求的内容已缓存在该节点,直接由此节点发送给用户,若内容未被缓存,该节点从源服务器或其他节点获取内容,进行缓存,并将其发送给用户 6 | - CDN 节点定期检查内容的有效性,并依据缓存策略更新,确保节点上的内容是最新的 7 | 8 | CDN 上的资源来自不同域名的原因: 9 | 10 | 1. 内容分发 11 | 2. 并行下载:浏览器对同一域名的并行下载数量有限制,大多数浏览器限制单个域名的并发连接数为 6 个左右,通过多个域名并行下载可突破这一限制 12 | 3. Cookie:主域名设置的 Cookie 被发送到所有子域名,为静态资源使用不同域名以避免发送无效的 Cookie,减少不必要的数据传输 13 | 4. 缓存:提高缓存利用率,不同静态资源被分配于不同子域名上,减少缓存冲突 14 | 15 | Domain Name System 作为域名和 IP 地址之间的映射系统,允许人们使用易于记忆的域名如 `example.com` 来访问特定服务端,而服务端实际上是通过 IP 地址如 `192.168.1.1` 来定位的 16 | 17 | DNS 查询流程:浏览器 DNS 缓存 -> OS 本地 `host` 文件 -> OS DNS 缓存 -> 网络请求 -> 本地服务器 -> 根域名服务器 -> 顶级域名服务器 -> 权威域名服务器 18 | 19 | DNSSEC 域名系统安全扩展验证 DNS 查询,返回响应并缓存相应信息,每个 DNS 记录均有 TTL,TTL 过期后删除缓存,后续请求重新触发完整的 DNS 查询流程 20 | 21 | 分层通过负载均衡分散压力,三级分层在实践中被证明既能满足全球互联网需求,又能保持稳定有效 22 | -------------------------------------------------------------------------------- /Computer Network/Chrome HTTP1.1 同一域名最大 6 个并发连接.md: -------------------------------------------------------------------------------- 1 | HTTP/1.1 虽支持持久连接,即通过一个 TCP 连接依次处理多个 HTTP 请求,但各个连接在同一时间只能处理一个请求即无真正的并发性,为提升性能,Chrome 默认为同一域名(准确的说,包括协议域名端口号)维护一个最多包含 6 个 TCP 连接的连接池,由于每个 TCP 连接一次只能处理一个请求,因此 6 个连接最多允许同时处理 6 个请求,当超过 6 个请求时,后续请求被放入队列等待空闲连接,若某个请求处理时间过长,同一连接上的后续请求被阻塞,这是 HTTP/1.1 的固有缺陷,此外 Chrome 根据请求类型和页面加载阶段动态调整请求优先级,优先加载关键渲染路径资源 2 | 3 | 1. 域名分片:将资源分配给多个子域名,各个子域名独立使用 6 个 TCP 连接 4 | 2. 端口分片:通过后端配置并支持多个端口监听,前端随机选择不同端口的 URL 发送请求 5 | 3. HTTP2 升级:HTTP/2 支持多路复用,允许在单个 TCP 连接上并发传输多个 HTTP 请求 6 | -------------------------------------------------------------------------------- /Computer Network/DNS host 文件配置错误.md: -------------------------------------------------------------------------------- 1 | 1. 定向错误:若 `hosts` 文件将域名错误指向不正确的 IP,用户在访问该域名时将被导航到错误的服务端 2 | 2. 服务中断:应用程序依赖于 `hosts` 文件配置来连接网络服务,若 `hosts` 文件将域名错误指向不正确的 IP,应用程序将无法连接到该网络服务 3 | 3. 安全风险:若 `hosts` 文件将域名错误指向不正确的 IP,用户在不知情的情况下输入敏感信息如用户名和密码等,有较大的安全风险 4 | 4. 调试困难 5 | 6 | ###### 排查错误 7 | 8 | - 验证文件路径是否正确,通常为 `C:\Windows\System32\drivers\etc\hosts` 9 | - 通过 `ping` 命令检查域名解析是否指向正确的 IP 如 `ping example.com` 应返回 `hosts` 文件中指定的 IP 10 | - 清除 DNS 缓存:在 Windows 中使用 `ipconfig /flushdns` 命令 11 | -------------------------------------------------------------------------------- /Computer Network/HTTP 请求头 & 响应头.md: -------------------------------------------------------------------------------- 1 | 请求头: 2 | 3 | - `Content-Type` 报文类型 4 | - `Content-Length` 内容长度 5 | - `Accept` 允许接收的数据类型 6 | * `Accept-Encoding` 允许接收的压缩方式 7 | - `Cookie` 用户凭证,包含服务器通过 `Set-Cookie` 响应头发送的一个或多个 Cookie 8 | - `Connection` 完成传输是否关闭 TCP 连接,`keep-alive`(保持连接)和 `close`(关闭连接) 9 | - `Host` 访问的主机域名,指定请求的目标服务器 10 | - `User-Agent` 浏览器类型,标识发起请求的客户端类型 11 | - `Cache-Control` 缓存策略,如 `no-cache`、`max-age` 等 12 | - `Expires` 缓存策略,已被上面的替代 13 | 14 | 响应头: 15 | 16 | * `Content-Type` 报文类型 17 | * `Content-Length` 内容长度 18 | * `Content-Encoding` 内容编码,指定响应体使用的压缩方式 19 | * `Set-Cookie` 设置 Cookie 20 | * `Access-Control-Allow-Origin` CORS 21 | * `Connection` 完成传输是否关闭 TCP 连接,`keep-alive`(保持连接)和 `close`(关闭连接) 22 | * `Server` 服务器信息,如 `Apache`、`Nginx` 23 | * `Location` 重定向目标地址 24 | - `Cache-Control` 缓存策略,如 `no-cache`、`max-age` 等 25 | - `Expires` 缓存策略,已被上面的替代 26 | - `Etag` 协商缓存限制条件,提供资源的唯一标识符(通常是一个哈希值),用于确定资源在服务器上是否已被修改 27 | - `Last-Modified` 协商缓存限制条件,标识资源最后一次被修改的时间 28 | -------------------------------------------------------------------------------- /Computer Network/IPv4 & IPv6.md: -------------------------------------------------------------------------------- 1 | IPv4 和 IPv6 用于网络设备间的通信 2 | 3 | 1. 地址长度 4 | 5 | - IPv4:32 位地址长度即 4 个十进制数,每个数字的范围从 0 到 255,以点号分隔如 192.168.0.1 6 | - IPv6:128 位地址长度即 8 组十六进制数,每组由 4 个字符组成,以冒号分隔如 2001:0db8:85a3:0000:0000:8a2e:0370:7334。这种格式允许压缩,省略内部的 0 以简化表示 7 | 8 | 2. 地址空间 9 | 10 | - IPv4:提供约 43 亿个独立地址,但不满足全球互联网设备日益增长的需求 11 | - IPv6:提供几乎无穷个独立地址即 3.4×10383.4×1038 个地址,可以满足全球互联网设备日益增长的需求 12 | 13 | 3. 地址分配和配置 14 | 15 | - IPv4:地址配置可手动完成或通过动态主机配置协议 DHCP 自动完成 16 | - IPv6:除支持类似 IPv4 的配置方式外,还支持无状态地址自动配置 SLAAC 17 | 18 | 4. 分组处理和路由 19 | 20 | - IPv4:头部结构相对复杂,包含许多选项,可在通信过程中修改,分组处理和路由较为复杂 21 | - IPv6:头部结构简单,不包含校验等不常用的选项,简化分组处理和路由 22 | 23 | 5. 广播和多播 24 | 25 | - IPv4:支持广播即发送数据包给网络上的所有设备 26 | - IPv6:不支持广播,支持多播即发送数据包给一组特定的目的地 27 | 28 | 6. 安全性 29 | 30 | - IPv4:未内置加密和认证,依赖应用层或第三方解决方案如 IPsec 31 | - IPv6:提供端到端的加密和数据完整性验证 32 | 33 | -------------------------------------------------------------------------------- /Computer Network/Iframe.md: -------------------------------------------------------------------------------- 1 | Inline Frame 为 HTML 元素,其通过创建一个独立的 DOM 和 JavaScript 环境,允许在一个页面中显示其他页面内容,同时与原页面保持交互独立性,若 iframe 与外部页面同源,则两者可直接通过 JavaScript 访问彼此的全局变量、函数和 DOM 等,否则即 iframe 与外部页面跨域,通过 `postMessage` 和 `onmessage` 进行跨域通信 2 | 3 | ```html 4 | 6 | ``` 7 | 8 | 1. 通过  `sandbox`  属性限制 Iframe 的行为 9 | 10 | - `allow-same-origin`:保持同源策略 11 | - `allow-scripts`:允许执行脚本 12 | - `allow-forms`:允许提交表单 13 | - `allow-popups`:允许打开新窗口 14 | 15 | 2. 模块化开发,独立加载子模块,适合微前端架构 16 | 3. 在 Chromium 中各个 Iframe 均创建自己独立的渲染进程,大量 Iframe 导致内存占用高,页面卡顿,同时搜索引擎可能忽略 Iframe 内容,对 SEO 不友好,响应式设计需动态调整宽高 17 | 4. XSS 攻击即嵌入恶意脚本的 Iframe,点击劫持即透明 Iframe 覆盖按钮,诱导用户点击,Phishing 钓鱼攻击即伪造登录页面的 Iframe 18 | -------------------------------------------------------------------------------- /Computer Network/JWT.md: -------------------------------------------------------------------------------- 1 | JSON Web Token 定义一种自包含的方式,作为 JSON 对象用于在客户端和服务端间传递信息,它由三部分组成,用句点 `.` 分隔: 2 | 3 | ```JSON 4 | const token = base64urlEncoding(header) + '.' + base64urlEncoding(payload) + '.' + base64urlEncoding(signature) 5 | ``` 6 | 7 | - Header 由两部分组成:令牌类型 `type` 和所使用的算法 `alg` 如 HMAC SHA256 或 RSA 8 | 9 | ```JSON 10 | { 11 | "alg": "HS256", 12 | "typ": "JWT" 13 | } 14 | ``` 15 | 16 | - Payload 包含一个实体 (通常为用户) 和其他数据的声明集 17 | 18 | ```JSON 19 | { 20 | "loggedInAs": "admin", 21 | "iat": 1422779638 22 | } 23 | ``` 24 | 25 | - Signature 由 header 和 payload 加密生成,确保它们在传输过程中未被篡改 26 | 27 | ```JSON 28 | HMAC_SHA256( 29 | secret, 30 | base64urlEncoding(header) + '.' + 31 | base64urlEncoding(payload) 32 | ) 33 | ``` 34 | 35 | ###### 工作流程 36 | 37 | - 当用户登录成功后,服务端返回一个 JWT 给客户端 38 | - 客户端在 localStorage 或 cookie 中储存该 JWT 39 | - 当客户端再次请求服务端时,在请求头中携带该 JWT 40 | - 服务端接收到请求后验证该 JWT,若验证成功,服务端认为该请求是合法的 41 | 42 | ###### 为什么使用 JWT ? 43 | 44 | - 实现无状态化,服务端无需存储 token,每次客户端发送请求,只需携带该 JWT 45 | - JWT 轻量、结构简单,可通过 URL、POST 参数或在 HTTP header 里发送 46 | - JWT 的信息集是自包含的,其中包含所有用户需要的信息,避免多次查询数据库 47 | 48 | ###### 局限性 49 | 50 | 虽然 JWT 提供一种简单的认证方法,但存在安全隐患,若其被拦截,它可被任何拥有该 JWT 的人使用,因此需用 HTTPS 进行传输 51 | -------------------------------------------------------------------------------- /Computer Network/Last-Midified & Etag 局限性.md: -------------------------------------------------------------------------------- 1 | `Last-Modified`:协商缓存限制条件,标识资源最后一次被修改的时间 2 | 3 | 1. 时间精度限制:`Last-Modified` 以秒为单位表示时间,若在一秒内多次修改资源,`Last-Modified` 无法准确反映最新状态,导致浏览器无法获取到最新资源 4 | 2. 弱验证:`Last-Modified` 只能告诉浏览器资源最后修改的时间,不能有效识别内容实际上不变而只是修改时间的情况,导致资源重新下载 5 | 3. 依赖服务端:`Last-Modified` 的值依赖于服务端的时间设置,若服务端时间有误,或客户端和服务端间存在时差,则影响协商缓存验证的准确性 6 | 7 | `Etag`:协商缓存限制条件,提供资源的唯一标识符,通常为哈希值,用于确定资源在服务端上是否已被修改 8 | 9 | 强弱验证:强验证 -> 内容有任何变化,`ETag` 即变化,而弱验证在一定程度上缓解该问题,但其判断标准模糊 10 | 11 | -------------------------------------------------------------------------------- /Computer Network/MAC.md: -------------------------------------------------------------------------------- 1 | MAC 媒体访问控制层为数据链路层的子层,由硬件和固件结合实现,硬件用于生成和校验 MAC 帧头部及 CRC 校验码,实现 CSMA/CD 算法以检测信号电平变化和碰撞检测,而在发生碰撞时,执行退避算法,等待随机退避时间后重传,固件则与操作系统网络协议栈对接,提供上层协议数据传递、配置接口和错误处理 2 | 3 | - 地址标识:各个网络设备均有唯一的 MAC 地址,用于在局域网内标识网络设备,MAC 层在帧中嵌入源和目的 MAC 地址以实现数据的定向传输 4 | - 帧封装与解封:MAC 层负责将上层数据封装成帧并在接收方解析它们以验证数据完整性 5 | - 访问控制:控制对共享传输介质的访问,保证同一时间只有一个设备在发送数据 6 | 7 | -------------------------------------------------------------------------------- /Computer Network/OSI 七层模型.md: -------------------------------------------------------------------------------- 1 | OSI 七层模型:各层均接收由它下一层所提供的特定服务且负责为自己的上一层提供特定服务,上下层间进行交互时所遵循的约定即接口,同一层间的交互所遵循的约定即协议,协议分层就如同计算机软件中的模块化开发,OSI 七层模型的建议是比较理想化的,它希望实现从第一层到第七层的所有模块并将它们组合起来实现网络通信,分层可将各层独立使用,即使系统中某些分层变化,也不会影响整个系统。通过分层细分通信功能,易于实现各个分层的协议并界定各个分层的具体责任和义务。而分层的局限性即过分模块化,逻辑复杂化,每个分层不得不实现相似的业务逻辑 2 | 3 | 1. 应用层:用于为应用提供服务并规定应用通信相关细节如 HTTP、SSL/TLS、DNS 和 SSH 4 | 2. 表示层:用于数据格式编码和转换,将应用固有的数据格式转换为网络标准传输格式,或将来自下层的数据转换为上层能够处理的格式 5 | 3. 会话层:用于管理会话,建立、维护和终止进程间通信及数据分割 6 | 4. 传输层:用于端对端通信,确保数据传输的完整如 TCP 和 UDP 7 | 5. 网络层:用于路由选择和寻址,实现数据包从源到目的地的传输如 IP 8 | 6. 数据链路层:用于物理层面上节点间数据传输,将物理层传输的比特流转换为数据帧并检测和纠正错误如 PPP 点对点协议协议、以太网协议、无线局域网协议、HDLC 高级数据链路控制协议 9 | 7. 物理层:用于在物理媒介上传输比特流,进行 01 比特流与电压高低、灯光闪灭的转换 10 | 11 | ![[Pasted image 20240530172822.png]] 12 | -------------------------------------------------------------------------------- /Computer Network/Ping.md: -------------------------------------------------------------------------------- 1 | Ping 基于 ICMP 协议(网络层),用于检测网络设备间的连通性、延迟和丢包情况 2 | 3 | 底层原理: 4 | 5 | 1. 源主机构造  ICMP Echo Request 报文(Type=8),包含序列号和时间戳,通过 IP 层发送至目标主机 6 | 7 | ``` 8 | | IP Header | ICMP Header (Type=8) | Payload (Data) | 9 | ``` 10 | 11 | 2. 目标主机接收到报文后,若网络正常且未被防火墙拦截,生成 ICMP Echo Reply 报文(Type=0),原样返回 Payload 12 | 3. 源主机接收到报文后,根据发送和接收时间差得出延迟,计算 RTT 往返时间,并通过发送次数与应答次数计算丢包率 13 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/HTTP Keep-Alive & TCP keepalive.md: -------------------------------------------------------------------------------- 1 | HTTP/1.1 默认开启 Keep-Alive,允许在一个 TCP 连接上发送和接收多个 HTTP 请求/响应,而无需每次交换数据时都重新建立连接,节约网络带宽和 CPU 资源,减少首屏加载时间,服务端为各个保持活动状态的连接分配资源,若有大量空闲连接,则消耗过多资源。客户端在 HTTP 请求头中包含 `Connection: keep-alive`,告诉服务端希望保持连接打开,以便发送后续请求,服务端同样在响应头中回复此字段,表示它同意保持连接打开 2 | 3 | TCP Keepalive:若在指定的时间内,连接上无任何数据传输,TCP 自动定期发送保活探测包即 Keepalive 探针以检测对方是否仍可响应,确认连接的有效性,若在指定时间内未接收响应,则认为连接已失效,自动关闭连接 4 | 5 | - 层次不同:HTTP Keep-Alive 工作在应用层,而 TCP Keepalive 工作在传输层 6 | - 配置:HTTP Keep-Alive 通过 HTTP 头部控制,依赖 HTTP 实现,TCP Keepalive 则由操作系统提供配置选项 7 | - 用途不同 8 | 9 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/MTU.md: -------------------------------------------------------------------------------- 1 | Maximum Transmission Unit:在一个网络传输层上可通过的最大数据包大小 2 | 3 | TCP 是一种面向连接的协议,它根据底层网络的 MTU 动态调整其段的大小即路径 MTU 发现,若一个 TCP 段大于网络的 MTU,IP 层需对其进行分片,使各个分片均小于 MTU,因此 TCP 通过 PMTUD 发现最大的数据包大小,避免在网络上的任一节点处进行分片,因为分片会增加重传的可能性 4 | 5 | UDP 是一种无连接的协议,不提供数据包的分片和重组功能,应用层需确保发送的数据包不大于网络的 MTU,否则数据包会在 IP 层分片,若不允许分片,可能丢失数据包 6 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP & UDP 与 IP 交互 & 发送数据.md: -------------------------------------------------------------------------------- 1 | 1. 数据封装:数据首先被发送到传输层的 TCP,TCP 对数据分段,并为各段添加 TCP 头信息,这些头信息包含源端口、目标端口、序列号、确认应答号等。TCP 将各段传输给网络层的 IP,IP 为每个 TCP 段添加 IP 头信息,这些头信息包括源 IP 地址、目标 IP 地址、生存时间 TTL 等。数据接着传输给网络接口层,封装成帧,并通过物理媒介发送 2 | 2. 路由选择:IP 层使用头信息中的目标 IP 地址来确定如何将数据包通过网络从源地址路由到目标地址 3 | 3. 数据接收和解封装:在接收端,IP 层首先处理到达的数据包,检查 IP 头信息,确认数据包已到达正确的目标地址,接着 IP 层移除 IP 头信息,将剩余的 TCP 段数据传输给传输层的 TCP,TCP 根据 TCP 头信息处理各段,进行重组、流量控制、错误检测等操作,最后 TCP 将重组后的数据按照正确顺序传输给应用层 4 | 5 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP & UDP 共用端口.md: -------------------------------------------------------------------------------- 1 | 1. TCP 和 UDP 是两种不同的协议,它们在操作系统的网络栈中分别独立实现,且端口号的概念在 TCP 和 UDP 中均存在,尽管 TCP 和 UDP 均使用端口号来标识连接和应用程序,但它们基于不同的协议,因此 TCP 和 UDP 端口空间是分开的 2 | 2. 在网络栈中,一个网络连接由源 IP 地址、目标 IP 地址、源端口号、目标端口号及协议这五元组来唯一确定,即使端口号相同但协议不同,则视为不同的应用 3 | 3. 从技术上讲,一个应用程序可使用 UDP 监听 80 端口,而与此同时,另一个应用程序使用 TCP 监听相同的 80 端口并不会产生冲突,这是因为端口号是协议特定的,所以 TCP 的 80 端口和 UDP 的 80 端口被视为两个不同端点 4 | 5 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP & UDP.md: -------------------------------------------------------------------------------- 1 | TCP 是一种面向连接的协议,通信双方在数据传输前必须建立连接,它通过序列号、确认应答、重传机制等确保数据可靠传输,且以正确顺序到达接收方,它通过滑动窗口机制实现流量控制,通过慢启动、快重传等机制来避免网络拥塞,此外它面向字节流,发送方可按照任意大小发送数据,而接收方将接收到的数据流重新组装起来 2 | 3 | UDP 是一种无连接的协议,无需在数据传输前建立连接即无需握手,它不能保证数据的可靠到达,即数据包可能丢失或顺序错乱,且没有内建的错误纠正机制,它是面向报文的,发送方发送的每个报文在接收方都是独立接收的,它支持多播和广播发送,可同时发送数据给多个接收方 4 | 5 | - 连接方式:TCP 是面向连接的,UDP 是无连接的 6 | - 可靠性:TCP 通过序列号、确认应答、超时重传、流量控制、拥塞控制和 Keepalive 保活机制等确保数据可靠传输,且以正确顺序到达接收方,UDP 无法保证数据的可靠到达,数据包可能丢失或顺序错乱且没有内建的错误纠正机制 7 | - 传输速度:由于建立连接和保证数据可靠性,TCP 传输速度比 UDP 慢 8 | - 用途差异:TCP 用于可靠数据传输的应用如 Web 页面加载和文件传输等,而 UDP 用于实时应用如流媒体和在线游戏等 9 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP 上的协议.md: -------------------------------------------------------------------------------- 1 | 1. HTTP & HTTPS 2 | 2. SSH:用于远程登录 3 | 3. DNS 4 | 4. Telnet:用于远程登录 5 | 5. FTP:用于文件传输 6 | 6. SMTP:用于发送邮件 7 | 8 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP 传送数据过程中断电 & 崩溃.md: -------------------------------------------------------------------------------- 1 | ###### 断电 2 | 3 | 1. 立即中断:断电导致所有正在运行的程序和网络活动立即停止,TCP 连接被迫中断,没有机会正常关闭连接 4 | 2. 无关闭握手:由于断电导致的中断是非正常的,TCP 连接没有进行四次挥手来正常关闭连接。因此对方因为没有接收到关闭连接的信号而保持连接状态,直到超时 5 | 3. 数据丢失:正在传输但未被确认的数据丢失,TCP 确保数据的可靠传输是通过接收方发送 ACK 实现的 6 | 7 | ###### 系统崩溃 8 | 9 | 1. 操作系统响应:操作系统因为某些原因停止正常工作,根据崩溃的具体情况,它可能释放该进程所持有的所有资源,关闭崩溃进程的所有套接字,对于 TCP 连接,操作系统向对方发送一个 RST 重置包,表明连接异常终止。当对方接收到 RST 包时,任何试图读写该 TCP 连接的操作都立即返回错误。根据其错误处理逻辑,对方可能停止发送数据、尝试重建连接、记录错误日志或采取其他恢复措施 10 | 2. 数据完整性:和断电类似,正在传输的数据可能因为崩溃丢失,若操作系统或 TCP 在崩溃前发送 FIN 包,则对方 TCP 执行关闭连接的流程,否则也会遇到类似断电情况的问题 11 | 3. 部分状态保存:若系统崩溃不是由硬件故障引起的,某些状态可能被保存下来 12 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP 头的标志位.md: -------------------------------------------------------------------------------- 1 | 1. URG:当置为 1 时表示紧急指针字段有效,接收方有紧急数据需优先处理 2 | 2. ACK:当置为 1 时表示确认序号字段有效 3 | 3. PSH:当置为 1 时表示推送字段有效,接收方立即从 TCP 接收缓冲区种提取数据,而不是等待缓冲区溢出 4 | 4. RST:当置为 1 时表示重置字段有效,TCP 连接出现严重问题,需强制断开连接 5 | 5. SYN:当置为 1 时表示同步字段有效,其为连接请求或接受段,用于同步序列号 6 | 6. FIN:当置为 1 时表示结束字段有效,发送方已达到数据传输末尾,可断开连接 7 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TCP 报文组成.md: -------------------------------------------------------------------------------- 1 | - 源端口和目标端口:各占 16 位,用于标识发送方和接收方 2 | - 序列号:32 位,用于保证 TCP 的可靠性和数据包顺序 3 | - 确认序号:32 位,用于表示接收到的数据字节序号 4 | - 数据偏移:4 位,表示 TCP 头部长度,用于指示数据部分的开始位置 5 | - 保留:6 位,保留未来使用,目前为 0 6 | - 标志位:上述 6 个标志位各占 1 位 7 | - 窗口大小:16 位,用于流量控制 8 | - 校验和:16 位,用于错误检测 9 | - 紧急指针:16 位,表示紧急数据的结束位置 10 | - 选项:长度可变,用于支持更灵活的通信需求如 MSS、窗口扩大因子等 11 | - 数据:跟随 TCP 头部,其长度可从数据偏移字段推断 12 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/TIME_WAIT.md: -------------------------------------------------------------------------------- 1 | TIME_WAIT 状态:四次挥手的最后阶段,客户端接收到服务端的最后一个 FIN 报文后,向服务端返回 ACK 应答报文,客户端进入 TIME_WAIT 状态,在此状态下,客户端等待 2 MSL 后断开连接。Maximum Segment Lifetime 是任何报文段被丢弃前在网络内的最长时间,RFC 793 定义的标准 MSL 为 2 分钟,因此 TIME_WAIT 状态的持续时间是 4 分钟 2 | 3 | ###### TIME_WAIT 状态的原因 4 | 5 | 1. 确保最后一个 ACK 报文能够到达:若客户端的最后一个 ACK 报文丢失,服务端将重传最后的 FIN 报文,TIME_WAIT 状态确保客户端有机会重新发送 ACK 报文响应重传的 FIN 报文 6 | 2. 等待足够时间以确保网络中所有报文均已到期:防止延迟的报文段在相同的四元组上之新连接中被错误接受 7 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/UDP 数据包大小.md: -------------------------------------------------------------------------------- 1 | UDP 数据包的长度是由其 16 位长度字段定义的,理论上最大长度是 `65,535` 字节,其头部占用 `8` 字节,因此数据部分的最大长度为 `65,527` 字节。由于 IP 层也有其长度限制且考虑到 IP 头部至少 20 字节,UDP 数据包的实际最大长度通常为 `65,507` 字节,但在实际中,还需考虑网络 MTU,以太网的标准 MTU 是 `1500` 字节,若 UDP 数据包大于该值,它需在 IP 层分片,这增加了丢包风险。因此为避免分片,我们通常使用更小的 UDP 数据包 2 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/三次握手的原因.md: -------------------------------------------------------------------------------- 1 | 1. 确认双方的发送与接收能力: 2 | 3 | - 第一次握手:客户端发送一个 SYN 同步序列报文,以开始连接,证明客户端能发送数据 4 | - 第二次握手:服务端返回一个 SYN-ACK 同步应答报文,以确认接收到 SYN,证明服务端能发送与接收数据 5 | - 第三次握手:客户端发送一个 ACK 确认报文,以确认接收到 SYN-ACK,证明客户端能接收数据 6 | 7 | 2. 初始化序列号:每个方向的连接均有一个独立的序列号,三次握手允许双方协商初始化这些序列号,确保数据传输顺序和可靠性 8 | 3. 防止失效的连接请求建立连接:若客户端发送的初始连接请求 SYN 在网络中延迟,且客户端重新发送该连接请求并建立连接、完成通信,则该延迟的连接请求到达服务端后仍可被接收,导致服务端错误建立一个新的连接,三次握手通过确认双方的发送与接收能力可避免此种情况发生,因为客户端不会对一个已失效的 SYN-ACK 进行确认 9 | 4. 两次握手无法解决上述问题,若只有两次握手,则无法确认接收方知道发送方已准备好接收数据。四次握手是不必要的,一旦客户端和服务端交换 SYN 和 ACK 报文,它们有足够的信息来进行通信,同时确认各自的发送与接收能力,四次握手不会提供额外的保障,反而增加延迟 10 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/为什么有了 TCP 还要用 UDP 实现一个可靠性传输.md: -------------------------------------------------------------------------------- 1 | Quick UDP Internet Connections 是一个基于 UDP 实现的传输层协议,由 Google 首次提出,用于改进 HTTP/2 的传输,解决 TCP 的一些性能问题,同时优化类似 TCP 的可靠性特性 2 | 3 | 1. 减少连接和握手时间:QUIC 基于 UDP 实现,只需一个往返时间 RTT 即可完成握手并开始通信,而 TCP + TLS 需 2 到 3 个 RTT,对于支持 0-RTT 的 QUIC,握手时间进一步缩短 4 | 2. 连接迁移:QUIC 的连接标识独立于底层 IP 地址,即使客户端 IP 发生变化,QUIC 连接也能保持不中断 5 | 3. 多路复用:尽管 HTTP/2 支持多路复用,但 TCP 的有序传输导致队头阻塞问题,单个慢请求阻塞后续所有请求,QUIC 解决了这一问题,它在应用层实现多路复用,每个流均独立 6 | 4. 拥塞控制:QUIC 内置改进的拥塞控制算法如 Google 的 BBR,它们可以更快适应网络条件变化,提供更稳定的吞吐量 7 | 5. 安全性:QUIC 从一开始就设计为安全的协议,它将 TLS 加密整合到协议本身,而不是作为一个附加层 8 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/半连接 & 全连接.md: -------------------------------------------------------------------------------- 1 | 当 TCP 连接完全建立时,即经过三次握手,客户端和服务端间的连接即为全连接 2 | 3 | - 第一次握手:客户端发送一个 SYN 同步序列报文,以开始连接,证明客户端能发送数据 4 | - 第二次握手:服务端返回一个 SYN-ACK 同步应答报文,以确认接收到 SYN,证明服务端能发送与接收数据 5 | - 第三次握手:客户端发送一个 ACK 确认报文,作为对 SYN-ACK 的确认,证明客户端能接收数据 6 | 7 | 半连接即 SYN 队列:在三次握手过程中,服务端接收到客户端的 SYN 报文后,发送 SYN-ACK 前的状态,即只完成了三次握手的前两步,服务端维护一个半连接队列,用于存放处于该状态的连接。半连接的存在是为处理并发连接请求,防止服务端资源被未完成连接的客户端过度占用,由于 SYN 报文可能因为网络延迟而导致服务端等待时间过长,设置半连接队列可在服务器资源有限的情况下管理这些未完成的连接请求。利用 TCP 的半连接状态,攻击者可发送大量的 SYN 报文而不完成后续的握手过程,导致服务端的半连接队列迅速填满,正常的连接请求因此被拒绝,这种攻击即 SYN 洪泛攻击。为抵御这种攻击,操作系统和网络设备实现多种策略如 SYN cookies,用于在不占用服务端资源的情况下完成三次握手 8 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/四次挥手的原因.md: -------------------------------------------------------------------------------- 1 | - 为彻底关闭两个方向上的数据传输通道,每个方向均需一个 FIN 报文来断开该方向的连接和一个 ACK 报文来确认断开 2 | * 若只有三次挥手,则至少有一个方向的连接断开未被单独确认,无法保证双方了解连接的关闭状态,导致一方误认为连接仍建立 3 | * 四次挥手已足够在两个方向上分别确认连接关闭,第一和第二次挥手完成从客户端到服务端的关闭确认,第三和第四次挥手完成从服务端到客户端的关闭确认,五次挥手是不必要的,并不会提供额外的保障,反而会增加延迟 4 | 5 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/数据从发送到接收的拷贝次数.md: -------------------------------------------------------------------------------- 1 | 1. 用户空间到内核空间:当客户端发送数据时,数据首先从用户空间拷贝到内核空间的 TCP 发送缓冲区 2 | 2. 内核空间到网络接口:数据从内核空间的 TCP 发送缓冲区拷贝到网络接口的发送队列 3 | 3. 网络接口到内核空间:当服务端接收数据时,数据从网络接口拷贝到内核空间的 TCP 接收缓冲区 4 | 4. 内核空间到用户空间:数据从内核空间的 TCP 接收缓冲区拷贝到用户空间 5 | 6 | ###### 优化 7 | 8 | 零拷贝:减少或消除从用户空间到内核空间的数据拷贝,如Linux 的 `sendfile` 系统调用可直接在内核中传输数据 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/查看 TCP 占用内存情况.md: -------------------------------------------------------------------------------- 1 | - 内核管理:在 Linux 中,TCP 等网络协议栈均由内核管理,内核负责分配和管理每个 socket 使用的内存,包括发送缓冲区和接收缓冲区 2 | - 缓冲区:TCP 的性能和内存使用密切相关,因为 TCP 使用缓冲区来存储待发送及已接收但未被应用读取的数据,缓冲区大小可通过 socket 选项调整 3 | - 内存压力和释放:当系统内存紧张时,内核尝试减少为 socket 分配的内存,影响 TCP 连接的性能,而当 TCP 连接关闭时,相关的内存资源被释放回系统 4 | 5 | 在 Linux 系统中,`/proc/net/sockstat` 和 `/proc/net/sockstat6` 文件提供关于 socket 使用情况的统计信息,包括 TCP、UDP 等协议的 socket。通过查看这些文件,可获取到当前系统级别的 socket 使用情况,包括打开的 socket 数量、内存使用等 6 | 7 | ```bash 8 | cat /proc/net/sockstat 9 | cat /proc/net/sockstat6 10 | ``` 11 | 12 | `ss` 和 `netstat` 用于查看系统中当前所有 TCP 连接的状态 13 | 14 | ```bash 15 | ss -tm 16 | ``` 17 | 18 | 显示每个连接的内存使用情况 `-m` 和定时器信息 `-t` 19 | 20 | ```bash 21 | netstat -tan 22 | ``` 23 | 24 | `/proc/[pid]/status` 文件提供特定进程的内存使用情况,其中 `[pid]` 是进程的 ID 25 | 26 | ```bash 27 | cat /proc/[pid]/status 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/第四次挥手若客户端 kill.md: -------------------------------------------------------------------------------- 1 | 1. 在此场景中,若客户端在发送最后一个 ACK 报文后立即被 kill 掉,TCP 连接仍将正常关闭,因为服务端在发送 FIN 报文并接收到客户端的 ACK 报文后,就认为连接已成功关闭 2 | 2. 若客户端在发送最后一个 ACK 报文前被 kill 掉,服务端无法接收到客户端的 ACK 报文,它的连接仍处于 LAST_ACK 状态,等待 ACK 报文的到来,正常情况下,客户端在发送最后一个 ACK 报文后进入 TIME_WAIT 状态,等待足够时间以确保服务端接收到 ACK报文,若客户端被 kill 掉,该阶段将被跳过。若服务端没有接收到最后的 ACK报文,它将重传 FIN 报文,等待客户端的 ACK报文,一旦超时,服务端将关闭连接并释放相关资源 -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/粘包.md: -------------------------------------------------------------------------------- 1 | 粘包:发送方的若干数据包被 TCP 合并为一个包进行发送,或接收方一次性接收多个数据包 2 | 3 | - TCP 面向流,数据的发送和接收是连续的字节流,没有固定边界 4 | - 网络延迟或拥塞控制导致的数据包合并 5 | 6 | ###### 解决方案 7 | 8 | 1. 消息定长:发送固定长度的消息,接收方根据固定长度分割接收到的字节流 9 | 2. 设置边界标志:在各包末尾添加特殊字符作为边界,接收方通过这些边界字符来拆分消息 10 | 3. 长度前缀:各包开始部分先发送一个表示消息长度的字段,接收方先读取长度字段,再根据长度读取相应数据 11 | 4. 应用层协议:定义复杂的应用层协议如在消息中使用 JSON 或 XML 格式,这样即使发生粘包,也可通过解析 JSON 或 XML 来识别单独的消息 12 | -------------------------------------------------------------------------------- /Computer Network/TCP & UDP/限制 TCP 最大连接数.md: -------------------------------------------------------------------------------- 1 | 1. 操作系统 2 | 3 | - 端口数:TCP 连接是通过端口号标识的,每个连接由源 IP 地址、目标 IP 地址、源端口号和目标端口号组成,由于端口号是 16 位的,理论上每个 IP 地址可拥有高达 65535 个端口,但实际可用端口数少于该理论值,因为某些端口号被系统保留 4 | - 最大文件描述符数:每个 TCP 连接在类 Unix 系统内核中均通过文件描述符来表示,操作系统对各个进程可打开的文件描述符数量有限制,这直接影响单个进程能打开的 TCP 连接数 5 | - 参数配置:如 Linux 系统中的 `/proc/sys/net/core/somaxconn` 参数可控制 socket 监听队列的最大长度,而`/proc/sys/net/ipv4/tcp_max_syn_backlog` 参数用于调整 SYN 接收队列的最大长度,这些间接限制 TCP 最大连接数 6 | 7 | 2. 硬件:每个 TCP 连接均消耗一定的内存和 CPU 资源,对于有大量并发连接的服务器,资源消耗限制 TCP 最大连接数 8 | 3. 网络:虽然网络带宽和延迟不直接限制 TCP 最大连接数,但它们影响数据传输效率,间接限制服务端有效处理的并发 TCP 连接数量 9 | 4. 程序本身 10 | -------------------------------------------------------------------------------- /Computer Network/preload & prefetch.md: -------------------------------------------------------------------------------- 1 | 2 | | | preload | prefetch | 3 | | ----- | --------------------------------- | ----------------------------- | 4 | | 目标 | 当前页面关键渲染路径资源(首屏 CSS、动态加载的脚本和 SDK) | 预测页面可能用到的非关键资源(下一页和动态路由组件等) | 5 | | 加载时机 | 优先级高,立即加载,无需等待浏览器空闲时 | 优先级低,浏览器空闲时加载 | 6 | | 缓存储位置 | 存储于内存,随页面关闭释放 | 存储于硬盘,跨页面存储,缓存时间由 HTTP 头部字段控制 | 7 | 8 | ```html 9 | 10 | 11 | 12 | 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /Computer Network/token 失效.md: -------------------------------------------------------------------------------- 1 | 1. 过期时间 2 | 2. 黑名单:可将不安全的 token 添加到黑名单中,每次接收请求时,检查 token 是否在黑名单中,如果在则拒绝该请求 3 | 3. 数据库存储:存储与 token 相关的状态于数据库中,如用户退出或更改密码时,使当前的 token 失效 4 | 4. 双 token 机制:Access Token 用于访问受保护的资源如 API,客户端在有效期内可用其认证状态和访问权限,其具有较短的有效期,风险相对较低,即便被泄露,攻击者也只能在短时间内使用它,Refresh Token 用于在 Access Token 过期后获取一个新的 Access Token,无需用户再次登录,Refresh Token 有更长的有效期,其安全性比 Access Token 高,因为它只用于与认证服务端通信,而不是直接用来访问受保护资源 5 | 5. 绑定 token 于特定 IP 或设备:即使 token 被窃取,攻击者无法从其他设备或 IP 上使用它,token 自然失效 6 | -------------------------------------------------------------------------------- /Computer Network/三次握手四次挥手.md: -------------------------------------------------------------------------------- 1 | 通过 TCP 三次握手与服务端建立连接,进行通信 2 | 3 | ![[Pasted image 20231030070246.png]] 4 | 5 | 客户端和服务端初始时为 CLOSED 状态,服务端主动监听某个端口,处于 LISTEN 状态 6 | 7 | ![[Pasted image 20231030070719.png]] 8 | 9 | 客户端随机初始化序号 client_isn ,将此序号置于 TCP 首部的|序号|字段中,同时将 SYN 置为 1,接着将第 1 个 SYN 报文发送给服务端,该报文不含应用层数据,此时客户端处于 SYN-SENT 状态 10 | 11 | ![[Pasted image 20231030070656.png]] 12 | 13 | 服务端接收到客户端的 SYN 报文后,它随机初始化序号 server_isn,将此序号填入 14 | TCP 首部的|序号|字段中,再将 client_isn + 1 填入|确认应答号|字段,将 SYN 和 ACK 置为 1,接着将该报文返回给客户端,该报文不含应用层数据,此时服务端处于 SYN-RCVD 状态 15 | 16 | ![[Pasted image 20231030070934.png]] 17 | 18 | 客户端接收到服务端报文后,向服务端发送最后一个应答报文,将 ACK 置为 1 ,再将 server_isn + 1 填入|确认应答号|字段,该报文可含应用层数据,此时客户端处于 ESTABLISHED 状态,服务端接收到客户端的应答报文后,进入 ESTABLISHED 状态 19 | 20 | 一旦完成三次握手,客户端和服务端即可进行通信,此后可通过四次挥手断开连接 21 | 22 | ![[Pasted image 20231030071543.png]] 23 | 24 | - 客户端打算关闭连接,发送一个 FIN 置为 1 的报文,客户端进入 FIN_WAIT_1 状态 25 | - 服务端接收到该报文后,向客户端返回 ACK 应答报文,服务端进入 CLOSED_WAIT 状态 26 | - 客户端接收到该报文后,进入 FIN_WAIT_2 状态 27 | - 服务端处理完数据后,向客户端发送 FIN 报文,服务端进入 LAST_ACK 状态 28 | - 客户端接收到该报文后,向服务端返回 ACK 应答报文,客户端进入 TIME_WAIT 状态 29 | - 服务器接收到该报文后,进入 CLOSED 状态 30 | - 客户端经过 2MSL 后,进入 CLOSED 状态 31 | -------------------------------------------------------------------------------- /Computer Network/前后端交互.md: -------------------------------------------------------------------------------- 1 | 前端 -> 展示数据和用户界面 2 | 后端 -> 处理业务逻辑、数据库操作 3 | 4 | ###### 工作流程 5 | 6 | 1. 用户在前端界面上进行操作,如点击按钮、提交表单等 7 | 2. 前端通过 ajax & axios & fetch 发送 HTTP 请求与后端进行通信 8 | 3. 后端接收请求,根据请求的内容和传递的数据执行相应的业务逻辑,同时操作数据库 9 | 4. 后端处理完毕后,将结果以 HTTP 响应的形式返回给前端 10 | 5. 前端根据响应的内容更新用户界面 11 | 12 | ###### 注意事项 13 | 14 | 1. API 规范:如请求方式、路径、参数、返回数据格式和错误处理等 15 | 2. API 文档:定期维护迭代更新,并保持前后端间良好的沟通与协作 16 | 3. API 版本控制:特别是在生产环境中,以免更新导致前端应用崩溃 17 | 4. 错误处理:后端应返回明确的错误码和警告信息,前端根据不同错误进行相应处理 18 | 5. 安全性:如数据加密、防止 SQL 注入、XSS、CSRF 攻击等 19 | 6. 性能优化:如合理设计数据库查询、缓存策略,减少不必要的数据传输等 -------------------------------------------------------------------------------- /Computer Network/前端缓存 & 资源更新问题.md: -------------------------------------------------------------------------------- 1 | 1. 浏览器缓存:当用户首次访问页面时,浏览器缓存页面资源如 HTML、CSS、JavaScript 和图片,当用户再次访问该页面时,浏览器直接从缓存中加载这些资源而无需再向服务端发送请求 2 | 3 | - Memory Cache:体积较小或频繁访问的资源存储在内存中,浏览器关闭时即被清除 4 | - Disk Cache:体积较大或很少访问的资源存储在硬盘中,持续时间长,但读取速度慢 5 | 6 | 2. 强缓存 & 协商缓存 7 | 3. LocalStorage & SessionStorage & Cookie & Session 8 | 4. Service Worker 9 | 5. IndexedDB:在浏览器中存储大量结构化数据的 API 10 | 6. 网关缓存如 Nginx 和 CDN 11 | 7. Redis 12 | 13 | 线上资源已更新但浏览器页面尚未更新,可能为线上资源实际未更新成功或浏览器页面缓存资源 14 | 15 | 手动刷新页面 F5:浏览器在请求中携带 `Cache-Control:max-age=0` 询问服务端资源是否更新 16 | 强制刷新页面 CTRL + F5:浏览器在请求中携带 `Cache-Control:no-cache` 向服务端请求新资源 17 | 18 | 1. 通过 `[contenthash]` 命名文件,当文件内容修改时,`[contenthash]` 变化导致请求 URL 变化,浏览器直接请求新资源 19 | 2. 在服务端或 CDN 实现版本控制,根据请求的版本标识符重定向至对应资源 20 | -------------------------------------------------------------------------------- /Computer Network/反向代理.md: -------------------------------------------------------------------------------- 1 | 出于安全原因,浏览器采用同源策略,禁止一个源的 HTML 或 JS 获取另一个源的资源以防止 XSS 攻击,但它也限制合法的跨域请求如 API 调用。反向代理是让客户端认为它仍在请求同源资源,但在后台,代理服务端将这些请求转发到目标服务端,由于浏览器的同源策略只针对浏览器,不针对服务端,因此无论是否同源,服务端间总能自由交流 2 | 3 | 1. 设置一个代理服务端,本地服务器或现有的云服务器均可 4 | 2. 配置代理规则,所有来自客户端的请求均转发到目标服务端,如当客户端请求 `https://your-domain.com/api/data` 时,代理服务端将其转发到 `https://target-domain.com/data` 5 | 3. 客户端请求代理服务端,由于两者同源,因此不会触发同源策略限制 6 | 4. 代理服务端接收到客户端的请求后,转发到目标服务端 7 | 5. 代理服务端从目标服务端接收响应后,将其返回客户端,客户端只知道代理服务端响应,如此一来,你成功绕过浏览器的同源策略限制 8 | -------------------------------------------------------------------------------- /Computer Network/密码登录.md: -------------------------------------------------------------------------------- 1 | 1. 密码存储:不直接存储用户的明文密码,首先将明文密码和一个随机字符串即盐值混合,即便多用户使用相同明文密码,由于盐值不同,其哈希值不同,接着使用 SHA-256、bcrypt 等哈希算法计算明文密码的哈希值,将之存储,哈希函数将任意长度的输入转换成固定长度的输出,此过程为单向的,无法从哈希值反向推导出原始密码 2 | 2. 密码传输 3 | 3. 密码验证:从登录请求中接收用户密码,使用与存储哈希值时相同的盐值对用户密码进行加盐和哈希计算,将计算出的哈希值与数据库中存储的哈希值进行比较,若两者匹配,验证用户身份成功,允许登录,否则拒绝访问 4 | -------------------------------------------------------------------------------- /Computer Network/强缓存 & 协商缓存.md: -------------------------------------------------------------------------------- 1 | ##### 强缓存 2 | 3 | 当客户端发起请求后,服务端在返回的响应头中携带相关的缓存策略,告诉客户端该资源的缓存期限。在此期间内,客户端不再向服务端请求该资源,而是直接从本地获取 4 | 5 | ###### 响应头 6 | 7 | 1. `Cache-Control` 8 | 9 | - `max-age=`:指定资源在本地的缓存期限 10 | - `must-revalidate`: 缓存过期后,需向服务端验证 11 | - `no-cache`:强制确认资源的有效性(实际上是进入协商缓存阶段) 12 | - `no-store`:禁止缓存 13 | - `public`:响应可被任何缓存存储 14 | - `private`:响应仅限于单用户,不能被共享缓存存储 15 | 16 | 2. `Expires` 现已被 `Cache-Control` 代替 17 | 18 | ##### 协商缓存 19 | 20 | 协商缓存需要客户端与服务端间的通信。当缓存过期时,客户端携带服务端之前返回的某些信息,询问服务端资源已被修改。若无修改,服务端返回 304 状态码,告诉客户端继续使用本地缓存,否则,服务端返回 200 状态码和新的资源 21 | 22 | ###### 请求头 23 | 24 | - `If-Modified-Since`: 客户端将之前服务端返回的 `Last-Modified` 值放到这个头部中,询问自那以后服务端资源是否已被修改 25 | - `If-None-Match`: 客户端将之前服务端返回的 `ETag` 值放到这个头部中,询问服务端资源是否已被修改 26 | 27 | ###### 响应头 28 | 29 | - `Last-Modified`:协商缓存限制条件,标识资源最后一次被修改的时间 30 | * `Etag`:协商缓存限制条件,提供资源的唯一标识符,通常为哈希值,用于确定资源在服务端上是否已被修改 31 | 32 | ###### 区别 33 | 34 | 1. 强缓存完全由客户端控制,资源直接从客户端本地获取,而协商缓存需要客户端向服务器发起请求,以确认服务端资源是否发生变动 35 | 2. 强缓存返回 200,协商缓存返回 304 或 200 36 | 3. 强缓存响应时间通常较快,因为资源直接从客户端本地获取,而协商缓存需要等待服务端响应 37 | 4. 强缓存通过 `Cache-Control` 和 `Expires` 实现,协商缓存通过 `ETag` + `If-None-Match` 和 `Last-Modified` + `If-Modified-Since` 实现 38 | 39 | 40 | -------------------------------------------------------------------------------- /Computer Network/扫码登录.md: -------------------------------------------------------------------------------- 1 | 1. 在登录界面生成一个包含特定登录信息的二维码 2 | 3 | ```JavaScript 4 | const sessionId = generateSessionId(); 5 | generateQRCode('https://example.com/login?sessionId=' + sessionId); 6 | ``` 7 | 8 | 2. 用户使用移动设备扫描该二维码,移动设备识别二维码中的信息,向后端发送验证请求 9 | 10 | ```JavaScript 11 | fetch('https://example.com/api/verify-login', { 12 | method: 'POST', 13 | headers: { 14 | 'Content-Type': 'application/json' 15 | }, 16 | body: JSON.stringify({ sessionId: sessionId }) 17 | }); 18 | ``` 19 | 20 | 3. 后端接收验证请求,完成验证,并返回响应 21 | 22 | ```JavaScript 23 | app.post('/api/verify-login', (req, res) => { 24 | const { sessionId } = req.body; 25 | }); 26 | ``` 27 | 28 | 4. 前端轮询或通过 WebSocket 接收后端的验证结果 29 | 30 | ```JavaScript 31 | function checkLoginStatus() { 32 | fetch('https://example.com/api/check-login-status?sessionId=' + sessionId) 33 | .then(response => response.json()) 34 | .then(data => { 35 | if (data.loggedIn) { 36 | } else { 37 | setTimeout(checkLoginStatus, 1000); 38 | } 39 | }); 40 | } 41 | 42 | checkLoginStatus(); 43 | ``` 44 | 45 | 5. 一旦后端验证成功,前端更新状态反映用户已登录 46 | -------------------------------------------------------------------------------- /Computer Network/本地 hosts 文件.md: -------------------------------------------------------------------------------- 1 | 修改本地 hosts 文件可解决跨域问题,让域名不经过 DNS 服务器直接指向特定 IP 地址。当你通过修改 hosts 文件,将公司内网的域名指向 `127.0.0.1` 本机地址或其他特定 IP 时,你其实是在伪装域名对应的服务端地址,当浏览器尝试访问该域名时,实际上访问的是本机或特定的服务器。若配置后的地址与请求的前端页面处于同一源下,即可绕过浏览器的同源策略限制 2 | 3 | 1. 打开 `C:\Windows\System32\drivers\etc\hosts` 文件,将 `company.internal` 解析到 `127.0.0.1`,直接在 hosts 文件中添加: 4 | 5 | ``` 6 | 127.0.0.1 company.internal 7 | ``` 8 | 9 | 3. 重启浏览器或在命令提示符执行 `ipconfig /flushdns` 清除 DNS 缓存 10 | 11 | ###### 注意事项 12 | 13 | - 修改 hosts 文件只适合开发和测试环境,不建议在生产环境中使用 14 | - hosts 文件只需列出 IP 或域名,无需给出端口 15 | * hosts 文件不支持通配符,我们无法通过配置自动匹配多个子域名,每个需要解析的子域名都要明确列出 16 | 17 | ``` 18 | 127.0.0.1 example.company.internal 19 | 127.0.0.1 example2.company.internal 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /Computer Network/清除浏览器缓存并删除 token,如何保持登录状态?.md: -------------------------------------------------------------------------------- 1 | 1. Access Token & Refresh Token 2 | 2. 服务端会话:服务端跟踪用户会话,非完全依赖于客户端 token。用户登录后,服务端创建会话并存储在数据库或内存中,它返回会话标识如会话 ID,客户端存储于 Cookie 中。用户在后续请求中携带会话标识,服务端通过会话标识查找对应会话。若用户清除浏览器缓存,丢失本地存储的会话标识,但可通过某种机制如自动登录 Cookie 来恢复会话 3 | 3. 自动登录:用户登录时选择自动登录选项,服务端生成一个长期有效的自动登录 token,其存储在 Cookie 中,当用户访问且无有效的会话时,服务端使用该 token 自动创建新的会话 4 | -------------------------------------------------------------------------------- /Computer Network/状态码.md: -------------------------------------------------------------------------------- 1 | - 100 Continue:客户端继续发送请求的其余部分 2 | - 200 OK:请求成功 3 | - 201 Created:请求成功且服务端创建新资源 4 | - 204 No Content:请求成功,但没有响应体数据返回 5 | - 206 Partial Content:请求成功,返回的响应体数据不是全部资源 6 | - 301 Moved Permanently:永久重定向,在响应头 `Location` 字段指定新 URL 7 | - 302 Found:临时重定向,在响应头 `Location` 字段指定临时 URL 8 | - 303 See Other:重定向到其他资源 9 | - 304 Not Modified:资源未更改,用于协商缓存 10 | - 307 Temporary Redirect:类似 302,但请求方法不能改变 11 | - 308 Permanent Redirect:类似 301,但请求方法不能改变 12 | - 400 Bad Request:客户端请求报文有误,服务端无法理解请求 13 | - 401 Unauthorized:请求需用户认证 14 | - 403 Forbidden:服务端拒绝执行请求,禁止访问资源 15 | - 404 Not Found:在服务端上未找到请求的资源 16 | - 405 Method Not Allowed:请求方法不被允许 17 | - 500 Internal Server Error:服务端未知错误 18 | - 501 Not Implemented:服务端暂不支持请求的功能 19 | - 502 Bad Gateway:服务端作为网关或代理时发生错误,服务端自身工作正常,但访问后端服务端发生错误 20 | - 503 Service Unavailable:服务端忙碌,暂时无法处理请求 21 | -------------------------------------------------------------------------------- /Computer Network/输入 URL 到页面展示的全过程.md: -------------------------------------------------------------------------------- 1 | 1. 解析用户输入内容:用户在地址栏输入内容后,浏览器判断用户输入是合法 URL 还是搜索内容,若为搜索内容则合成 URL,若为合法 URL 即可加载 2 | 2. 查看是否命中强缓存,没有则下一步 3 | 3. DNS 解析 4 | 4. 三次握手 5 | 5. 查看是否命中协商缓存,发送 HTTP 请求并接收响应 6 | 6. 四次挥手 7 | 7. 提交文档 8 | 8. 浏览器渲染 9 | -------------------------------------------------------------------------------- /Data Structure/Array.prototype.sort.md: -------------------------------------------------------------------------------- 1 | `Array.prototype.sort` 在 ES10 前为非稳定的,从 ES10 后为稳定的,其在 ECMAScript 标准中无明确指定使用某一排序算法,因此不同 JavaScript 引擎有不同实现,对于包含多种数据类型元素的数组,`sort` 首先将元素统一转换为字符串,再进行比较(除非提供比较函数),若提供比较函数,`sort` 使用该函数的返回值来决定元素间的排序关系 2 | 3 | 1. V8 引擎(Chrome, Node.js):插入排序 -> 10个以内元素数组,快排 + Timsort -> 大于10个元素数组 4 | 2. SpiderMonkey(Firefox)& JavaScriptCore(Safari):归并排序 5 | 6 | Timsort 结合插入和归并排序的优点,其时间复杂度为 O(n log n),将输入数组拆分为多个小块,大小为 32 或 64,使用插入排序对单个小块进行排序,最后使用优化过的归并排序将所有小块拼接成最终的数组 7 | 8 | -------------------------------------------------------------------------------- /Data Structure/DFS & BFS.md: -------------------------------------------------------------------------------- 1 | BFS:从根节点开始层层遍历节点,可使用队列来实现,从队列中取出一个节点,访问该节点的所有未访问过的邻居节点,将其添加到队列中,重复上述过程直至队列为空。BFS 在无权图中可以找到从起始节点到其他所有节点的最短路径,在高宽度的图中,其需在内存中保存大量的节点引用 2 | DFS:从根节点开始遍历某一分支直到找到叶子节点,接着回溯并通过先前访问过的节点继续遍历其他分支,可以用递归或栈实现,访问根节点并标记其为已访问,对每一个未被访问过的相邻节点递归调用 DFS,重复上述过程直至所有节点均被访问过,DFS 比 BFS 的内存开销少,只需存储一条从根节点到当前节点的路径,但无法保证找到最短路径,因为它深入遍历每条路径 3 | -------------------------------------------------------------------------------- /Data Structure/二叉搜索树 & 平衡二叉树.md: -------------------------------------------------------------------------------- 1 | 二叉搜索树:每个节点包含一个键和它关联的值,对于树中的任意节点 `x`,其左子树中的所有键均小于 `x` 的键,其右子树中的所有键均大于 `x` 的键,每个节点均有左右子节点,这些子节点也是二叉搜索树,增删查找的平均时间复杂度为 O(log n),其依赖于树的高度,若二叉搜索树高度过高且在极端情况下,其退化为一个链表,时间复杂度降至 O(n) 2 | 平衡二叉树:为解决上述问题,平衡二叉树应运而生,其继承二叉搜索树的性质,增加额外的平衡条件,保持树的高度为 log n,如 AVL 树和红黑树。按照二叉搜索树的规则插入节点,在回溯过程中更新各个节点的高度并计算平衡因子,若发现某个节点的平衡因子超出 [−1,1][-1,1][−1,1] 的范围,则根据不同情况 LL、LR、RR 和 RL 进行旋转操作以恢复平衡 3 | -------------------------------------------------------------------------------- /Data Structure/判断有向图是否存在环.md: -------------------------------------------------------------------------------- 1 | - DFS 和递归栈:遍历各个节点时,使用一个递归调用栈记录当前递归路径中的节点,使用一个数组记录所有被访问过的节点,若在递归过程中发现某个邻接节点已在当前的递归栈中,则说明存在环 2 | - 拓扑排序:对有向图进行拓扑排序,通过不断移除入度为 0 的节点,若得到一个包含所有节点的拓扑序列,则说明图是无环的,反之则存在环 3 | -------------------------------------------------------------------------------- /Data Structure/十大排序时空复杂度.md: -------------------------------------------------------------------------------- 1 | 1. 冒泡排序: 2 | 3 | - 时间复杂度:最好情况 -> O(n) + 数组完全有序,最坏情况 -> O(n²) + 数组完全逆序,平均情况 -> O(n²) 4 | * 空间复杂度:O(1) -> 原地排序 5 | 6 | 2. 选择排序: 7 | 8 | - 时间复杂度:最好/最坏/平均情况 -> O(n²) + n-1 次选择 9 | * 空间复杂度:O(1) -> 原地排序 10 | 11 | 3. 插入排序: 12 | 13 | - 时间复杂度:最好情况 -> O(n) + 数组完全有序,最坏情况 -> O(n²) + 数组完全逆序,平均情况 -> O(n²) 14 | * 空间复杂度:O(1) -> 原地排序 15 | 16 | 4. 快速排序: 17 | 18 | - 时间复杂度:最好/平均情况 -> O(n log n) ,最坏情况 -> O(n²) + 选取基准为最小或最大元素 19 | * 空间复杂度:O(log n)/O(n) -> 递归深度 20 | 21 | 5. 归并排序: 22 | 23 | - 时间复杂度:最好/最坏/平均情况 -> O(n log n) + 始终遍历所有元素并进行合并 24 | * 空间复杂度:O(n) -> 创建一个与原数组相同大小的辅助数组来合并分组 25 | 26 | 6. 希尔排序: 27 | 28 | - 时间复杂度:最好情况 -> O(n log n) + 间隔序列,最坏情况 -> O(n(log n)²) 29 | * 空间复杂度:O(1) -> 原地排序 30 | 31 | 7. 堆排序 32 | 33 | - 时间复杂度:最好/最坏/平均情况 -> O(n log n) 34 | * 空间复杂度:O(1) -> 原地排序 35 | 36 | 8. 桶排序 37 | 38 | - 时间复杂度:最好情况 -> O(n+k) ,最坏情况 -> O(n²) + 所有元素分配于同一桶,平均情况 -> O(n+k) 39 | * 空间复杂度:O(n+k) -> 需额外空间来存储桶 40 | 41 | 9. 计数排序 42 | 43 | - 时间复杂度:最好/最坏/平均情况 -> O(n+k) + k 为输入数据的范围 44 | * 空间复杂度:O(k) -> 需额外空间来存储计数数组 45 | 46 | 10. 基数排序 47 | 48 | - 时间复杂度:最好/最坏/平均情况 -> O(nk) + k 为数字的最大位数 49 | * 空间复杂度:O(n+k) -> 需额外空间来存储数位 50 | -------------------------------------------------------------------------------- /Data Structure/哈希冲突.md: -------------------------------------------------------------------------------- 1 | 哈希冲突:使用哈希表或哈希映射存储键值对时,不同键通过哈希函数得到相同的哈希值,由于哈希表的索引依赖于哈希值,相同的哈希值意味着两个键定位于同一位置。哈希表的核心即哈希函数,其将键映射到一个整数,该整数作为数组索引,哈希函数需满足:哈希值均匀分布,尽可能减少哈希冲突 + 快速计算 + 相同输入始终产生相同输出 2 | 3 | 1. 开放寻址法:一旦发生哈希冲突,按某种顺序探测其他位置并将键值对存储于其中 4 | 2. 链表法:数组索引不直接存储元素,而是存储链表,所有具有相同哈希值的元素均被添加到该链表中 5 | 6 | JavaScript 的 Object 和 Map 均基于哈希表实现,对象可使用任意数据类型作为键,但底层上将其转换为字符串 7 | -------------------------------------------------------------------------------- /Data Structure/堆 & 栈.md: -------------------------------------------------------------------------------- 1 | 栈:后进先出,其大小在程序启动时确定,即可能发生 Stack Overflow。JavaScript 使用栈管理函数调用,每次调用函数时,调用参数和局部变量被推入栈,当函数执行完毕,它们弹出,控制权返回给函数的调用者 2 | 堆:其大小不固定,用于动态分配内存,可随时申请和释放空间,与栈相比有更强的灵活性,但存取速度相对较慢。堆内存由操作系统的内存管理器控制,程序在运行时从堆中申请块状内存区域来存储数据,每当程序请求堆内存时,操作系统提供一个内存块,并在内部记录该内存块的位置和大小,便于访问和管理。JavaScript 的引用数据类型和闭包等存储于堆中,其生命周期不是由创建它们的上下文直接控制,而是由 JavaScript 垃圾回收机制管理 3 | -------------------------------------------------------------------------------- /Data Structure/拓扑排序.md: -------------------------------------------------------------------------------- 1 | 拓扑排序:一种对有向图的顶点进行排序的算法,用于任务调度、解析表达有先后依赖关系的数据、编译原理的指令序列化、项目构建的依赖处理等,其为每个顶点创建一个线性顺序,使得对于任何从顶点 𝑢u 到顶点 𝑣v 的有向边,𝑢u 在排序中均出现在 𝑣v 前。拓扑排序只可能出现在有向无环图中,因为有环图无法满足所有依赖关系。其基于顶点的入度,遍历图的个边,计算所有顶点的入度,选择一个入度为 0 的顶点,入度为 0 意味着没有其他顶点指向该顶点,这样的顶点可作为排序的起点,将选中的顶点添加到拓扑排序的结果中,并在图中移除该顶点及其所有出边,重复上述过程,直到所有顶点均被移除或无入度为 0 的顶点 2 | 3 | - 基于队列的 Kahn 算法:使用队列来保存所有入度为 0 的顶点,每次从队列中取出一个,将其添加到拓扑排序的结果中且移除其所有出边,若此过程中某顶点的入度减为 0 则将其入队,重复上述过程直到队列为空 4 | - 基于 DFS 的算法:对图进行深度优先搜索,每访问一个顶点及其所有邻接点后,将其推入栈中,最终栈中的元素顺序即为拓扑排序之逆序 5 | -------------------------------------------------------------------------------- /Data Structure/时间复杂度 & 空间复杂度.md: -------------------------------------------------------------------------------- 1 | 时间复杂度:描述算法执行时间与输入数据间的关系,用于表示算法执行时间随输入数据增长的增长率,大 O 表示法忽略常数因子和低阶项,关注最影响性能的主要因素 2 | 3 | O(1) -> 哈希查找 4 | O(log n) -> 二分查找 5 | O(n) -> 单层循环 6 | O(n log n) -> 快排和归并 7 | O(n^2) -> 嵌套循环 8 | O(2^n) -> 斐波那契数列递归 9 | 10 | 空间复杂度:描述算法执行过程中占用存储空间的大小,大 O 表示法,其考虑的是除存储输入数据外的额外空间如调用栈、对象存储和结构化数据的处理 11 | 12 | O(1) 13 | O(n) 14 | O(log n) -> 递归深度 15 | -------------------------------------------------------------------------------- /Data Structure/树 & 图.md: -------------------------------------------------------------------------------- 1 | 树:有一个根节点,从根节点开始通过连接的边访问各个节点,除根节点外的各个节点有且仅有一个父节点,各个节点有零或多个子节点,n 个节点有 n-1 条边,无环的连通图 2 | 图:非层级结构,表示多对多的关系,任何节点均可被访问且无特定的起始节点,可以有环,图可为有向或无向的,图可为连通或不连通的,边可带权重 3 | 4 | -------------------------------------------------------------------------------- /Data Structure/稳定 & 不稳定.md: -------------------------------------------------------------------------------- 1 | 若两个相等的元素在排序前后保持同一相对顺序,则该排序算法为稳定的,如冒泡、插入和归并等排序,在处理涉及多个字段的数据时,稳定的排序算法保证当对一个字段进行排序后,先前按另一字段排序后的顺序仍被保留 2 | 若两个相等的元素在排序前后可能改变其相对顺序,则该排序算法为不稳定的,如快速排序,快速排序的不稳定性来源于分区过程,相等的元素在分区时根据其遇到基准的顺序被移至基准的某侧,这可能改变其初始的相对顺序 3 | -------------------------------------------------------------------------------- /Data Structure/红黑树 & B 树 & B+ 树.md: -------------------------------------------------------------------------------- 1 | 红黑树:自平衡二叉搜索树,每个节点均有一个颜色属性,根节点和叶子节点为黑色,每个红色节点均有两个黑色的子节点,从任一节点到其叶子节点的所有简单路径均包含相同数量的黑色节点,其通过一系列规则和旋转操作维持树的平衡,确保在最坏情况下基本操作的时间复杂度为 O(log n),用于实现内存中的数据结构如 Java 的 TreeMap 和 TreeSet 2 | B 树:有多个子节点,所有叶子节点位于同一层,当节点过多触发节点分裂,当节点过少触发节点合并,其通过维持低高度来优化 I/O 操作,用于存储系统如数据库和文件系统,高效执行排序和增删查找等操作 3 | B+ 树:继承 B 树优点,进一步优化顺序访问数据等操作,叶子节点存储数据指针并通过指针相连,内部节点仅存储键值对即索引,增大分支因子,降低树高,有利于全局扫描 4 | -------------------------------------------------------------------------------- /Data Structure/链表 & 数组.md: -------------------------------------------------------------------------------- 1 | 数组:在 JavaScript 中数组内存可根据所需动态调整,数组中的元素依照顺序存储,即各元素紧贴前一元素存储,通过起始地址和索引即可直接计算出任一元素的内存地址,因此查找元素时间复杂度为 O(1),在数组中增删元素需移动目标元素前/后所有元素,因此增删元素的时间复杂度为 O(n) 2 | 链表: JavaScript 无内置的链表数据结构,但可使用对象模拟,链表中的元素可存储在内存中的任一位置,各个节点均包含数据和指向下一节点的引用,访问任一元素需遍历链表直到找到目标元素,因此查找元素时间复杂度为 O(n),在链表中增删元素只需改变其前后节点的引用,因此增删元素的时间复杂度为 O(1) 3 | -------------------------------------------------------------------------------- /Data Structure/队列.md: -------------------------------------------------------------------------------- 1 | 队列:先进先出,允许在一端添加元素,在另一端删除元素,入队 Enqueue、出队 Dequeue、查看队首元素 Peek、检查队列是否为空 IsEmpty 和获取队列长度 Size,JavaScript 数组提供 `push` 和 `shift` 实现队列,但 `push` 和 `shift` 可能需要移动数组中所有元素即 O(n)的时间复杂度,而使用链表实现队列增删元素的时间复杂度为 O(1),因为只需修改指针 2 | -------------------------------------------------------------------------------- /Front-End Engineering/两个 JavaScript 文件循环引用.md: -------------------------------------------------------------------------------- 1 | CommonJS 的模块加载是动态的,在运行时执行,循环引用时,未初始化的模块返回部分导出为空的对象 2 | 3 | 而 ES Module 基于静态分析,在编译时执行,循环引用时,在解析阶段建立导出和导入的绑定关系,但模块是按顺序执行的,未初始化的模块被访问时抛出 ReferenceError 4 | -------------------------------------------------------------------------------- /Front-End Engineering/内存泄漏检测.md: -------------------------------------------------------------------------------- 1 | JavaScript 垃圾回收机制策略即引用计数 + 根可达性分析,内存泄漏的本质为本应被垃圾回收的 JavaScript 对象仍被意外引用如全局变量(使用严格模式禁止隐式全局变量 + ESLint 配置 `no-undef` 检测未声明变量 + 使用 `WeakMap` 或 `WeakSet` 弱引用临时数据 + 手动释放) + 闭包引用(手动释放) + 未移除的事件监听器和定时器(组件销毁时移除) + 未设置上限或清理策略而累积的缓存(LRU 算法限制缓存大小) + console.log(手动释放) 2 | 3 | 1. Memory 面板:Heap Snapshot 生成堆快照,查看对象内存分配,Allocation Timeline 跟踪内存分配时间线,Allocation Sampling 统计内存分配来源 4 | 2. Performance 面板:观察内存曲线是否持续增长,呈阶梯式增长 -> 定时器未清除,呈持续增长而无下降趋势 -> 全局变量或缓存泄漏 5 | 3. Performance Monitor:实时监控记录并可视化 JavaScript 堆内存、GPU 内存、document、DOM 节点和事件监听器 6 | 4. 源码断点调试:在可疑代码处设置 `debugger`,通过调用堆栈分析引用链 7 | 8 | 以闭包泄漏为例:打开页面执行可疑操作,手动触发 Collect garbage 按钮以生成快照,多次 Delta 快照对比,观察 `JS Arrays` 或闭包对象数量变化,查找 Retainers 中内存增长的 JavaScript 对象,定位到闭包引用链 9 | -------------------------------------------------------------------------------- /Front-End Engineering/微信小程序.md: -------------------------------------------------------------------------------- 1 | App Service 逻辑层与 WebView 渲染层分离,通过 `Native` 层桥接通信,数据传递通过 `evaluateJavascript` 实现,原生组件直接由 Native 渲染,与 WebView 中的组件混合渲染时的层级问题,通过 `subpackages` 配置分包加载(主包 ≤ 2MB,总包 ≤ 20MB),代码注入优化,减少 `App.onLaunch` 同步逻辑,异步非关键任务,避免频繁 `setData`,合并数据更新,使用 `WXS` 处理轻量级逻辑,长列表使用 `recycle-view` 或 `virtual-list` 复用节点,敏感接口在 `app.json` 中声明 2 | -------------------------------------------------------------------------------- /Front-End Engineering/执行 npm run dev 到页面展示的全过程.md: -------------------------------------------------------------------------------- 1 | ```js 2 | npm run dev 3 | → 读取配置 4 | → 依赖预构建 5 | → 启动开发服务器 + 文件监听 6 | → 浏览器请求 HTML + 注入 HMR 客户端 7 | → 拦截请求 + 按需编译文件 + 处理依赖引用 8 | → 动态加载模块 + 增量更新 9 | → 框架初始化 + 页面渲染 10 | ``` 11 | 12 | 1.  通过 `package.json` 中的 `scripts`  字段,执行 `npm run dev` 命令,Vite 读取项目根目录的  `vite.config.js`,合并默认配置和用户自定义配置如插件、服务器端口和代理等 13 | 2.  依赖预构建,通过 ESBuild  打包 CommonJS/UMD 模块为 ES Module,生成预构建的依赖文件并存储于  `node_modules/.vite` 目录,浏览器后续直接加载预构建后的依赖,避免重复编译 14 | 3.  启动基于 Koa 的轻量级开发服务器,其负责处理文件请求、代码转换和热更新 15 | 4.  当用户访问页面时,Vite 返回 HTML 入口文件如 `index.html`,若 HTML 中存在 ` 9 | ``` 10 | 11 | `href`:用于建立当前元素和引用资源间的链接,如 ``, ``, `` 等 12 | 13 | ```HTML 14 | Visit Example.com 15 | ``` 16 | 17 | ```JavaScript 18 | 19 | ``` 20 | -------------------------------------------------------------------------------- /HTML/自定义属性.md: -------------------------------------------------------------------------------- 1 | 自定义属性(也称为数据属性)在 HTML 中是一种能够存储额外信息的机制,这些信息不会有任何的视觉表示,但可以通过 JavaScript 或 CSS 使用。HTML5 规范中允许我们添加非标准的属性,只要它们以 `data-` 为前缀 2 | 3 | 这些属性是为了提供一种方法以便我们能够在标准的 HTML 元素上存储自定义数据,而不是为每个可能的数据类型或数据结构创建新的、非标准的属性,这些数据可以被 JavaScript 在运行时用于创建一个动态的用户界面。自定义数据属性是不会影响到 HTML 的有效性的,也就是说,使用它们不会使你的 HTML 代码不符合验证 4 | 5 | 假设我们有一个文章列表,我们想要在每篇文章上存储额外信息,例如文章 ID: 6 | 7 | ```HTML 8 |
9 | ... 10 |
11 | ``` 12 | 13 | 在这个例子中,`data-post-id` 和 `data-author` 都是自定义数据属性。这些属性可以通过 JavaScript 使用,例如: 14 | 15 | ```JavaScript 16 | var article = document.getElementById('post-1'); 17 | 18 | var postId = article.getAttribute('data-post-id'); 19 | var author = article.getAttribute('data-author'); 20 | 21 | console.log(postId, author); // 12345 JohnDoe 22 | ``` 23 | 24 | 或者,你可以使用更现代的 `dataset` 属性来访问自定义数据属性: 25 | 26 | ```JavaScript 27 | var postId = article.dataset.postId; 28 | var author = article.dataset.author; 29 | 30 | console.log(postId, author); // 12345 JohnDoe 31 | ``` 32 | 33 | 在 CSS 中,你可以使用自定义属性作为选择器,如为作者 Clown 的文章添加特殊样式: 34 | 35 | ```CSS 36 | article[data-author="Clown"] { 37 | border: 1px solid blue; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /HTML/行内元素 & 块级元素.md: -------------------------------------------------------------------------------- 1 | ``` 2 |