阅读须知
本篇是由本人整理的前端知识点,并不全面,其中有一部分列出重点,而大部分只有标题,详细内容请自行搜索。
主要内容为基础知识,包含部分进阶知识,不涉及 node.js,框架以 React 为主。
1 浏览器
1.1 V8引擎
1.1.1 jit
1.1.2 js 执行环境 event loop
(macro)task主要包含:
- script(整体代码)
- setTimeout
- setInterval
- I/O
- UI交互事件
- postMessage
- MessageChannel
- setImmediate(Node.js 环境)
microtask主要包含:
- Promise.then
- MutaionObserver
- process.nextTick(Node.js 环境)
1.2 垃圾回收算法
1.2.1 标记清除
过程:
- 标记:从根对象开始遍历递归,把访问到的对象打上标记(可达)(一般用深度优先,因为使用的内存少)
- 清除:遍历堆内存,把未标记的对象加入空闲链表,标记的对象去除标记(为了做下一次标记)
- 分配:搜索空闲链表,找到合适的块(分配时垃圾回收)
- 合并:对内存中连续的垃圾合并,减少碎片
缺点:
- 碎片化
- 分配速度慢(遍历空闲链表)
- 与写时复制冲突,导致大量数据需要复制
- STW 时间长(因为都需要遍历堆)
写时复制:只有进程空间的各段要发生变化时,才将父进程的内容复制一份给子进程。
1.2.2 引用计数
- 一个引用类型赋值给变量时,引用计数是1
- 同一个值赋给另一个变量,引用计数加1
- 包含这个值引用的变量取得了另一个值,引用计数减1
- 引用计数变为0时,可以回收
问题:循环引用
IE9之前的 BOM 和 COM 使用 C++ 以 COM 形式实现,而 COM 的垃圾回收是用引用计数策略。
1.3 跨域
- JSONP
- CORS
CORS
- 预检请求:OPTIONS,携带实际请求的相关信息,获知服务器是否允许该实际请求(缓存时间内,同一请求无需再发起预检)
- 简单请求:不会触发预检请求
withCredentials
和Access-Control-Allow-Credentials: true
(因为跨域时 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息 Cookie)- 响应头字段
Access-Control-Allow-Origin
:允许访问的外域URIAccess-Control-Expose-Headers
:设置除Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma之外的允许浏览器访问的字段Access-Control-Max-Age
:指定预检请求的结果能够被缓存多久Access-Control-Allow-Credentials
:当浏览器的credentials设置为true时是否允许浏览器读取response的内容Access-Control-Allow-Methods
:用于预检请求响应,实际请求允许的方法Access-Control-Allow-Headers
:用于预检请求响应,实际请求允许的头部字段
1.4 FileReader
1.5 base64
1.5.1 图片转 base64
- 用户上传文件:使用
FileReader
的readAsDataURL(file)
- 项目或在线的图片:用 canvas 绘制后使用
canvas.toDataURL()
2 网络协议
2.1 TCP、UDP
2.2 HTTP
2.2.1 状态码
- 301 永久移动,应使用新URI
- 302 临时移动
2.2.2 请求头、返回头
2.2.3 常用 MIME 类型
- application/json
- application/javascript
- text/html
- text/css
- image/jpeg
- image/png
2.2.4 版本区别
HTTP/0.9
- 只支持GET
- 只能返回HTML格式
HTTP/1.0
- 支持GET、POST、HEAD
- 支持任何格式
- 必须包含头信息
- 新增状态码、多字符集支持、多部分发送、权限、缓存、内容编码等
- 每次TCP只能发送一个请求
HTTP/1.1
- 持久连接,TCP连接默认不关闭,可复用
- 管道机制,一个TCP连接可并发多个请求(所有的数据通信是按次序进行的)
- Content-Length,告诉浏览器本次响应的长度,区分数据包
- 新增动词方法
HTTP/2
- 头信息和数据体都是二进制,称为帧,解析更高效
- 双工(双向、实时),避免队头堵塞,同时发请求和响应
- 头信息压缩:gzip或compress;客户端和服务端同时维护头信息表,只发送索引
- 支持服务器推送
HTTP/3
使用基于UDP的QUIC协议
- 0RTT建立连接
- 多路复用(QUIC原生支持),丢包重传不存在TCP队头阻塞
- 加密认证的报文
- 向前纠错机制:每个数据包包含部分其他数据包的数据,少量的丢包可以通过其他包的冗余数据组装无需重传
2.2.5 缓存
2.2.5.1 强制缓存和协商缓存
- 强制缓存:expires、cache control,不会向服务端发请求,状态码200
- 协商缓存:last modified(秒级)、Etag,发请求返回304
2.2.5.2 cookie
document.cookie 设置
用处:
- 会话状态管理
- 用户个性化设置
- 浏览器行为跟踪
httponly: document.cookie无法访问,不能被JS调用
不设置 expires 或 max-age,浏览器关闭时自动删除。
设置 domain 使 cookie 包含在子域名
2.2.5.3 localStorage
setItem、getItem、removeItem、clear,操作是同步的
- 访问一个源
- 长期保留
- 键值对、字符串形式
2.2.5.4 sessionStorage
- 访问一个源
- 会话结束清除
2.2.5.5 indededDB
- 键值对存储,支持所有类型,包括JS对象和二进制(ArrayBuffer和Blob)
- 异步,不会锁死页面
- 支持事务、索引
- 同源限制
- 储存空间大,不少于250MB
2.2.6 HTTPS
过程:
- 客户端发送请求连接到服务器的443端口(随机数1+支持的加密算法)
- 服务器返回握手响应(随机数2+匹配的加密算法)
- 服务器发送第二个响应返回数字证书(颁发机构、过期时间、服务端公钥、签名、域名信息等)
- 客户端解析证书,验证是否有效,没问题则生成预主秘钥
- 客户端用随机数1、随机数2和预主秘钥组装会话秘钥,用证书公钥加密,发给服务端
- 服务端使用私钥解密获得会话密钥
- 客户端通过会话密钥加密一条消息发给服务端
- 服务端通过会话密钥加密一条消息回传给客户端,如果客户端能还接收则SSL层连接建立完成
优点:
- SEO:谷歌、百度排名更高
- 安全:可认证用户和服务器;防止数据被窃取、改变;现行框架下最安全的解决方案
缺点:
- 安全性
- 加密范围有限,黑客攻击、拒绝服务攻击、服务器劫持等起不到作用
- SSL证书的信用链体系不安全
- 成本
- SSL证书需要购买申请
- SSL证书通常需要绑定IP,不能在同一个IP绑定多个域名,IPv4资源不可能支撑这个消耗
- HTTPS协议会使页面加载时间延长近50%,增加10%到20%的耗电
- 连接缓存不如HTTP高效,流量成本高
- 连接服务端资源占用高很多
- 握手阶段比较耗时,对网站响应速度有影响
2.2.7 安全
2.2.7.1 XSS
- 用户输入的内容编码
- cookie 设置 httponly
2.2.7.2 CSRF
- 校验 referrer
- 请求参数携带 token
- 请求头携带 token
2.3 WebSocket
3 HTML
3.1 HTML5
3.2 语义化
3.3 meta
4 JS
4.1 基础
4.2 类型
4.3 作用域
4.4 Ajax
4.5 异步
4.5.1 Promise
4.5.2 generator
4.6 DOM 操作
4.7 事件
4.8 数组
4.9 对象
4.10 字符串
4.11 对象与继承
4.11.1 默认模式
4.11.2 借用构造函数
4.11.3 借用并设置原型
4.11.4 共享原型
4.11.5 临时构造函数
5 React
5.1 MVVM概念
5.2 虚拟 DOM
5.2.1 Dom diff
5.3 父子间通信
5.4 数据绑定
5.5 context
不需要传props就能传递数据贯穿组件树的方式。
React.createContext
React.createContext(defaultValue)
只有当组件在没有匹配的 Provider 时才会使用 defaultValue
注:传undefined时并不会使用defaultValue
Context.Provider
<MyContext.Provider value={/* some value */}>
- 从 Provider 到它子孙消费者的传播不受
shouldComponentUpdate
影响 - 数据变化是通过
Object.is
比较的
Class.contextType
class MyClass extends React.Component {
static contextType = MyContext;
render() {
let value = this.context;
/* render something based on the value */
}
}
包括 render
在内的生命周期都能使用 this.context
消费最近的 context
Context.Consumer
订阅 context 变化的组件。
<MyContext.Consumer>
{child 是个函数}
{value => /* render something based on the context value */}
</MyContext.Consumer>
使用多个 context 时需要多个 context.Privider 和对应的 context.Consumer
5.6 redux
5.6.1 reselect
避免无效的重复计算,结果缓存
5.6.2 immutable
- 结构共享
- 对象使用 hashCode 比较
5.6.3 react-redux
connect
使用 context 获取 store 数据
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
使用:
class A extends Component {}
connect(mapStateToProps, mapDispatchToProps)(A)
mapStateToProps(state, props)
:返回store数据,通过HOC,将store的数据作为props绑定到组件上mapDispatchToProps(dispatch, ownProps)
:将action作为props绑定到组件上
Provider
react-redux 的容器组件,将外界传给它的props.store
放到context
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
//使用 redux 的 createStore 方法创建的一个 store
let store = createStore(todoApp);
// store 作为一个 prop 传给 Provider 组件
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
5.6.4 redux-saga
用来处理异步任务的中间件,采用 Generator 函数来 yield
Effects。
优点:
- action 是原始对象,和redux同步的action一样
- 集中处理异步操作,异步接口一目了然
- 通过 Effect,方便异步接口的测试
- 通过 worder 和 watcher 可以实现非阻塞异步调用,并且同时实现非阻塞调用下的事件监听
- 异步操作的流程是可以控制的,可以随时取消异步操作
5.6.5 redux-thunk
将 action 从一个对象变成一个函数,任务执行方式是从 UI 组件直接触发任务。完成异步操作后执行 dispatch。
缺点:
- action 是一个函数,函数主体内不统一,且异步操作分散,不易维护
5.7 高阶函数 HOC
-
本质:是一个传入参数为函数的函数
-
问题:
- 引用传递,如需使用元组件的ref,使用
React.forwardRef
- 静态方法无法被传出,使用函数导出或方法复制
- 不能在 render 里使用,每次会返回一个新组件
- 引用传递,如需使用元组件的ref,使用
5.8 渲染策略
- shouldComponentUpdate
- PureComponent:每次的 props 或 state 的都是一个指向新引用的对象时适用,浅比较对象中的每一个属性值
- stateless function:父组件控制何时渲染和渲染内容
- 避免props不必要的更改:
- render中不要重新定义函数,使用bind
- 使用稳定的key
- store 范式化
- 不变时对象浅复制
5.9 react hooks
React 16.8 添加的,可以在函数组件里使用 state 和其他 react 功能。
useState
useEffect
:componentDidMount
,componentDidUpdate
,componentWillUnmount
useContext
:useContext(MyContext)
等于static contextType = MyContext
或<MyContext.Consumer>
useReducer
:const [state, dispatch] = useReducer(reducer, initialState);
useCallback
:返回一个被储存的 callback,只有当其中一个依赖变化时才会变useMemo
:返回一个被储存的值,只有当其中一个依赖变化时才重新计算,如果依赖没有值则每次render都计算。useRef
5.10 SSR
数据脱水和注水
6 CSS
6.1 基础
6.1.1 弹性布局rem/em
6.1.2 vh/vw/vm
6.1.3 响应式
6.1.4 flex 布局
6.2 预处理
6.2.1 LESS
6.2.2 SASS
6.3 CSS module
6.4 CSS 计算
6.4.1 CSS 变量
7 Hybrid 混合开发
7.1 常见问题
取不到设备宽度
7.2 白屏时间长和优化
8 构建
8.1 AMD/CMD/UMD/CommoonJS/ES Module
解决的问题、区别
8.2 babel(pollify)
babel 7
8.3 webpack
分片加载
- CommonJS:
require.ensure(dependencies, callback)
- AMD:
require(dependencies, callback)
- CommonsChunkPlugin
8.3.1 webpack4 优化
- noParse:忽略对部分没采用模块化的文件的递归解析和处理(如jQuery)
- IgnorePlugin:打包时忽略本地化内容
- DllPlugin:把第三方库单独打包到一个文件中
- Happypack:将 loader 由单线程转为多线程
- Tree-Shaking:基于 import/export 语法,在编译的过程中获悉哪些模块并没有真正被使用,在最后打包的时候会被去除
9 性能
9.1 懒加载
9.2 防抖和节流
- 防抖:可能最后只执行一次。
- 节流:在间隔时间周期内最多执行一次。