主要介绍一下前端中高级需要了解的前端手写代码合集, 并且会尽力编写测试用例,如果大家有兴趣可以一起提供测试用例和编码。让我们一同进步
每个目录下有对应的 index.html
文件可用于浏览器调试
-
- new - new.js
-
- call - call.js
-
- apply - apply.js
-
- bind - bind.js
-
- 函数 currying (科里化) && unCurrying - curry.js
-
- debounce - debounce.js
-
- throttle - throttle.js
-
- aop 面向切面编程 - aop.js
-
- XMLHttpRequest - ajax.js
-
- Jsonp 跨域请求 - jsonp.js
-
- cookie 读取、写入和删除 - cookie.js
-
- sleep - sleep.js
-
- Dom事件、事件委托/代理 - dom.js
-
- bigNumber - bigNum.js
-
- 深拷贝 - deepClone.js
-
- Promise(符合 Promise / A+ 规范) - myPromise.ts
-
- generator
-
- await / async - async.ts
-
- 添加遍历器
-
- 从 0 到 100 的累加 - accumulator.js
-
- 手写发布订阅(EventBus)- eventBus.ts
-
- 获取用户代理 - userAgent.js
-
- 数字千位分隔符 - separate-number/index.js
-
- possMessage 通讯 - possMessage/index.js
-
- Object.is 判断两个变量相等 - is.js
-
- 不产生新数组去重 - removeDuplicates.js
-
- 将 rgba 转为 16 进制颜色 - rgba2num.js
-
- 大文件上传 - large-upload/index.js
-
- 长列表优化 - long-list/index.js
-
- 图片懒加载实现 - lazy-load/index.js
-
- JS 图片压缩 - compress/index.js
-
- 楼栋导航
-
- react createElement
-
- react hooks
-
- Koa2 简易实现(进阶)
-
- vue 双向绑定原理(进阶)
-
- axios 手写实现 - lazy-load/index.js
-
- 垂直居中的四种方案 - vetically/index.html
-
- 瀑布流 - waterfall/index.html
-
- 圣杯布局 - grail/index.html
-
- 左中右三列布局,左右固定 220px, 中间自适应且先加载 - three-cols/index.html
-
- 冒泡排序 - bubbleSort.js
-
- 选择排序 - selectSort.js
-
- 插入排序 - insertSort.js
-
- 希尔排序 - shellSort.js
-
- 归并排序 - mergeSort.js
-
- 快速排序 - quickSort.js
-
- 堆排序 - heapSort.js
-
- 计数排序
-
- 基数排序
-
- 桶排序
-
- 拓扑排序
-
- 计算素数 - primes.js
LRU (Least Recently Used)
LRU 算法就是一种缓存淘汰策略, LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据
-
- LRU 缓存数据结构设计 - lru/index.js
LFU 缓存
LFU
-
- leetcode 121. 买卖股票的最佳时机
相关题目
-
- 缺失的数字 - bit/missing-number.js
-
- 找不同 - find-the-difference.js
位运算实用总结
功能 | 示例 | 位运算 |
---|---|---|
去掉最后一位 | (101101 -> 10110) | x >> 1 |
在最后加一个0 | (101101 -> 1011010) | x << 1 |
在最后加一个1 | (101101 -> 1011011) | x << 1 + 1 |
把最后一位变成1 | (101100 -> 101101) | x |
把最后一位变成0 | (101101 -> 101100) | x |
最后一位取反 | (101101 -> 101100) | x ^ 1 |
把右数第k位变成1 | (101001 -> 101101,k=3) | x |
把右数第k位变成0 | (101101 -> 101001,k=3) | x & ~ (1 << (k - 1)) |
右数第k位取反 | (101001 -> 101101,k=3) | x ^ (1 << (k - 1)) |
取末三位 | (1101101 -> 101) | x & 7 |
取末k位 | (1101101 -> 1101,k = 5) | x & ((1 << k)-1) |
取右数第k位 | (1101101 -> 1,k = 4) | x >> (k-1) & 1 |
把末k位变成1 | (101001 -> 101111,k = 4) | x |
末k位取反 | (101001 -> 100110,k = 4) | x ^ (1 << k-1) |
把右边连续的1变成0 | (100101111 -> 100100000) | x & (x + 1) |
把右起第一个0变成1 | (100101111 -> 100111111) | x |
把右边连续的0变成1 | (11011000 -> 11011111) | x |
取右边连续的1 | (100101111 -> 1111) | (x ^ (x + 1)) >> 1 |
去掉右起第一个1的左边 | (100101000 -> 1000) | x & (x ^ (x - 1)) |
判断奇数 | (x & 1) == 1 | |
判断偶数 | (x & 1) == 0 |
-
- leetcode 84. 柱状图中最大的矩形
滑动窗口
-
- 字符串子串问题
链表操作
-
- 链表成环
-
- 链表倒数第 K 个
-
- 链表找中点
-
- 二分法查找 - binarySearch.js
-
- twoSum 问题 - twoSum.js
-
- 斐波那契
-
- 爬楼梯
-
- 01背包
回溯模板
- 路径
- 选择列表
- 结束条件
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
-
- 全排列问题(数字不重复) - permute.js
-
- 全排列问题(数字可重复) - permuteUnique.js
-
- N皇后问题
-
- 子集 - subsets.js
-
- 组合 - combine.js
-
- 解数独 - solveSudoku.js
BFS: 广度优先算法,主要使用的构建一个 Queue 再遍历 Queue
DFS: 深度优先算法,主要是递归
一般来说:能用 BFS 解决的遍历都可以用 DFS 解决
-
- 电话号码的字母组合 - letter-combinations.js
-
- 合并二叉树 - mergeTrees.js
-
- 二叉树的锯齿形层序遍历 - binary-tree-zigzag-level-order-traversal.js
-
栈 Stack
-
- 栈数据结构的实现 - stack.ts
-
-
数组 Array
-
- 由于 js 原生实现了数组,所以这里不冗余实现
-
-
队列 Queue
-
- 队列数据结构的实现 - queue.ts
-
-
哈希表 HashMap
-
- js 中的对象和 ES6 中的新数据类型 set 都可以是 HashMap 数据结构
-
-
链表 NodeList
-
- 单链表 - list-node.js
-
- 双向链表
-
- 循环链表(跳表)
- 链表常规操作
-
- 找中点 - middle.js
-
- 翻转链表 - reverse.js
-
- 合并链表
-
-
-
树 Tree
-
- 二叉树的序列化与反序列化 - serialize.js
-
- 二叉树
-
- 二叉树的深度 - maxDepth.js
-
- 是否平衡二叉树 - isBalanced.js
-
- 对称的二叉树 - isSymmetric.js
-
- 从中序遍历和后序遍历构建二叉树 - buildTree.js
-
- 二叉搜索树 - bst.js
- 二叉搜索树的插入
- 二叉搜索树的查找
- 二叉搜索树的删除
- 第 K 大的元素
- 平衡二叉树
- B 树 (前端不常考)
- B+ 树 (前端不常考)
- 红黑树 (前端不常考)
- AVL树 (前端不常考)
-
-
- 堆(优先队列) Heap - heap.ts
- 优先队列
- 大顶堆、小顶堆
- 堆的构建
- 堆化
- 上浮
- 下沉
- 堆排序
- 最 K 大值的
-
- 图 Graph - graph.ts
- 有向图
- 无向图
- 顶点和边
- 邻接表表示 和 邻接矩阵表示
- 图的常见问题
- 找到小镇的法官 - find-the-town-judge.js
-
- 并查集UF Union-Find - union-find/uf.ts
- 实现 API
union()
连接两个节点connected()
判断两个节点是否连通count()
返回图中有多少个连通分量
- 特性
- 自反性:节点 p 和 p 是连通的。
- 对称性:如果节点 p 和 q 连通,那么 q 和 p 也连通。
- 传递性: 如果节点 p 和 q 连通,q 和 r 连通,那么 p 和 r 也连通。
- 优化
- 平衡性优化: 加入重量
size
- 路径压缩:
find()
加入parents[x] = parents[parents[x]]
- 平衡性优化: 加入重量
- 并查集的常见问题
-
字典树 - Trie.js
首先说起软件设计模式,就必须说到 SOLID 设计原则
SOLID 设计原则
头字母 | 缩写 | 中文 | 阐述 |
---|---|---|---|
S | SRP | 单一职责原则 | 让一个类只做一种类型责任,当这个类需要承当其他类型的责任的时候,就需要分解这个类 |
O | OCP | 开放封闭原则 | 对扩展是开放的,而对修改是封闭的 |
L | LSP | 里氏替换原则 | 当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系 |
I | ISP | 接口分离原则 | 高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象 |
D | DIP | 依赖倒置原则 | 使用多个专门的接口比使用单一的总接口总要好 |
23 种设计模式
GoF 一共有 23 种设计模式
按目的可分成三类:创建型模式
、结构型模式
、行为型模式
按作用范围可分为两类:类模式
、对象模式
但是 Javascript 不是 Java 那种传统的面向对象语言,至少没有原生实现接口编程,所以在 Js 中用设计模式还是有一定的技巧的,甚至一些设计模式在 Js 中有更加特殊的写法。另外有些设计模式并不大适用于 Javascript
-
- 单例模式 - single/index.js
-
- 工厂模式
-
- 原型模式
-
- 建造者模式(前端不常见)
-
- 适配器模式
-
- 代理模式
-
- 发布订阅模式
-
- 策略模式
-
- 职责链模式
-
- 命令行模式
-
- 状态模式
元字符 | 描述 |
---|---|
\ | 转义符 |
^ | 匹配开头 |
$ | 匹配结尾 |
* | 匹配任意次(0 个或者多个) |
+ | 匹配 1 次或者多次 |
? | 匹配 0 次或者多次(有或者没有) |
. | 匹配所有除"\n" 和 "\r" 的任何单个字符 |
{n} | 匹配限定 n 次 |
{n,} | 匹配至少 n 次 |
{n, m} | 匹配限定 n 到 m 次 |
x|y | 匹配 x 或 y |
[xyz] | 字符集合,匹配集合中任意一个 |
[a-z] | 字符范围 |
[^a-z] | 取反集合 |
\s | 匹配任何不可见字符 |
\S | 匹配任何可见字符 |
\d | 匹配一个数字字符 |
\D | 匹配一个非数字字符 |
() | 组 |
| | or 运算 |
(?=pattern) | 前置匹配 |
(?!pattern) | 前置不匹配 |
(?<=pattern) | 后置匹配 |
(?<!pattern) | 后置不匹配 |
\1 | 反模式(捕获组) |
- 我们需要尽可能的去让我们的正则表达式准确化,越准确的正则表达式匹配时,他的回溯情况就越少,所以它的性能就越高。
- 在正则表达式已经没有办法再进行优化的情况下,我们可以先选取一些没有回复情况的特征值进行先置条件判断,这样的话,我们能够尽量多的去避免一些无意义的好事匹配,优化我们的性能。
- 借助其他线程(
Web Socket
)或者服务来进行正则处理,避免用户卡顿。
最重要的是要解决三个问题(参考 BetterScroll):
- 插件管理:每个插件必须遵守并实现一些规范
- 插件连接:通常的办法是 注册表机制
- 插件通信:可以使用发布订阅方式
-
- TCP: 拥塞窗口,流量控制,快速重传,超时重传
-
- HTTP
- 预请求
- HTTP1.1
- HTTP2.0
- webpack 自己总结笔记
- 你的 import 被 webpack 编译成什么了 - 李永宁
- 深入Webpack-编写Loader - 浩麟
- Webpack - Loader
- 每个实现都需要通过测试用例
- git commit 已经使用 commitizen 包管理,我们用 git cz 提交符合 Angular 风格的校验规则 参考
项目有一些章节需要用到网络请求,如手写原生 Ajax
, 跨域请求
等
本项目已经搭建了 koa2
服务器,可以用于网络请求
Koa2
服务的目录为 /services
本地开发开启 Koa2
服务:
根目录下运行:
node run nodemon
如果需要添加路由:
/services/routes/index.js
添加路由文件/services/controllers
编写路由控制器
// 根目录下
npm run test