导图社区 前端面试归纳
导图归纳了一些前端面试的问题,包括HTML、CSS、JS、HTTP、优化、方案、安全、浏览器、框架、架构、实践、工程化、软、简单算法、高级应用、Pendding。大家一起学习吧!
编辑于2020-09-26 10:45:49前端面试归纳
HTML
doctype
web页面使用哪个HTML版本的指令
不是HTML标签
html5
<!DOCTYPE html>
CSS
盒模型
盒模型描述这些矩形盒子中的每一个。这个模型描述了元素所占空间的内容。每个盒子有四个边:外边距, 边框, 内填充边与 内容。
将所有元素表示为一个矩形盒
两种
标准
box-sizing: content-box
width = content
IE
box-sizing: border-box
width = content+padding+margin
IE盒模型用的最多,也是被推荐使用的
常见定位方案
普通流 normal flow
按照先后位置从上而下布局
行内元素水平排列,直到当行被沾满然后换行
块级元素则会被渲染为完整的新行
所有元素都是普通流定位
BFC
Block Formatting Context
定义
是区域:布局过程中生成块级盒子的区域,独立的容器和布局环境
有规则:浮动元素与其他元素的交互限定区域
通俗来讲
BFC是一个封闭的大箱子,内部无论如何变化,都不会影响到外部
创建
根元素 body
overflow 值不为 visible 的块元素
浮动元素 float不为none
绝对定位元素
position为absolute和fixed
行内块元素
inline-block
弹性元素
网格元素
规则
继承了普通流的定位规则
容器里的子元素不会影响到外面的元素
BFC的高度包含了内部的浮动元素
BFC区域不会与外部的浮动元素重叠
垂直方向的距离由margin决定。属于同一个BFC的两个相邻的Box的margin会发生重叠。
应用
外边距折叠(Margin collapsing)
有的译成外边距塌陷
规范
相邻盒子(可以是兄弟或祖先关系?)的外边距可以结合成一个单独的外边距
发生情况
属于同一个BFC的块级元素
在normal flow的布局中
也就是说绝对定位元素和浮动元素不会发生折叠
垂直方向相邻
块级盒子
也就是说inline-block不会发生折叠
也就是说水平方向不会发生折叠
解决
放在两BFC中
BFC可以包含浮动的元素
场景描述
一个block元素中,包含一个浮动元素,此时block元素会失去高度
解决
为block元素加入overflow:hidden属性,触发BFC
那么容器就回包裹着元素
阻止被浮动元素覆盖
两列布局
浮动 float
元素首先按照普通流的位置出现
然后脱离文档流,根据浮动的方向尽可能的向左或右偏移
绝对定位 absolute positioning
元素整体脱离普通流
不会影响其兄弟元素
具体坐标由决定定位的坐标决定
position和zindex
zindex
z-index值只决定同一父元素中的同级子元素的堆叠顺序
z-index只能在position属性值为relative或absolute或fixed
z-index值可以控制定位元素在垂直于显示屏方向(Z 轴)
Style标签放置的最佳位置
head 里,提前加载样式
常见行内元素和块级元素
行内
b, em, strong,
a, br, img, span, sub, sup
button, input, label, select, textarea
块级
canvas,div,dl,footer,form,h1,header,hr,p,pre,section,table,ul,li
居中
水平居中
行内元素
text-align: center
块级元素
定宽
margin: 0 auto
不定宽
flex
inline-block + text-align:center
垂直居中布局
文本垂直居中
line-height:height
margin + translate
表格
flex
justify-content
主轴
align-center
交叉轴
margin: auto
margin + top
很好用的css3技能但可能比较少人知道的点
vw、vh
calc
transition
inline和inline-block
inline
不会独占一行
多个相邻的行内元素会排列在同一行里,直到一行排列不下
置width,height属性无效
水平margin、padding无效,垂直margin、padding有效
block
独占一行
默认情况下,block元素宽度自动填满其父元素宽度
可以设置width,height属性
可以设置margin和padding属性
margin和padding属性,水平方向产生效果
inline-block
对象呈现为inline对象,但是对象的内容作为block对象呈现
margin: 0 auto水平居中原因
水平方向独占一行
auto是自动分配剩余空间的意思
清除浮动
利用overflow清除浮动
clear
利用伪元素(clearfix)
父元素结束标签之前插入清除浮动的块级元素
利用clear样式
css *号
*可以继承
从后向前
!important>行内样式>ID选择器 > 类选择器 | 属性选择器 | 伪类选择器 > 元素选择器
权重
选择器匹配规则
从右向左
探究 CSS 解析原理
JS
XMLHttpRequest
new XMLHttpRequest()
xhr.open
onload
this.status == 200||this.status == 304
jquery实现Ajax
dom操作
基础
查
document.getElementById
document.querySelector
创建
document.createElement
document.createTextNode
修改
appendChild
insertBefore
replaceChild
删除
removeChild
JS交换两个节点如何实现
事件
本质
事件驱动
浏览器中很多行为是异步
会创建事件并放入执行队列,等待当前代码执行完成
GUI渲染线程与JS引擎线程互斥
绑定,监听,委托的区别
绑定
HTML直接绑定
在JavaScript代码中绑定
绑定事件监听函数
事件委托
一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。
好处
减少重复工作
减少内存消耗
异步事件驱动
浏览器有一个内部大消息循环,Event Loop(事件循环),会轮询大的事件队列并处理事件
只有前面的处理完毕了,空闲了才会执行这个事件
事件流
冒泡
事件捕获
目标阶段
事件冒泡 (常用)
宏任务&微任务
promise & setTimeout
new & Object.create
Object.create(proto, [propertiesObject])
new 的过程?
Object.create(null)
无原型的对象
JavaScript是单线程还是多线程
单线程的,每个window包含一个JS线程
深拷贝和浅拷贝区别
子对象
模块化
好处
封装
可复用性
分类
CommonJS
服务端环境
在浏览器端,模块需要提前编译打包处理
基于文件
同步加载
首次加载模块后,会缓存
输出的是一个值的拷贝
AMD?
AMD规范则是非同步加载模块,允许指定回调函数
为浏览器环境设计
异步
回调函数形式
ES6 import
标准
输入值的引用
基于文件
静态分析
必须被用在其他语句或表达式的外部,而不能使用在if等代码块内部
原因之一是模块语法需要让 JS 能静态判断需要导出什么,正因为此,你只能在模块的顶级作用域使用 export与import
异步
CMD
CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行
UMD
整合AMD和CMD,自动判断当前环境
循环引用问题
commonjs
加载时执行
输入已执行部分
ES6
动态引用,不存在这个问题
遇到import不会去执行模块,而是只生成一个引用
而是用到的时候再去取值
js异步操作
回调函数
执行一个函数时,在函数内部处理操作,把操作结果以参数形式传入回调函数中
坏处
回调地狱
不利于阅读
不利于调整回调顺序
好处
代码清晰地表达出了执行关系
监听事件
定时器
宏任务
ajax
Ajax请求确实是异步的,这请求是由浏览器新开一个线程请求,事件回调的时候是放入Event loop单线程事件队列等候处理
Promise
标准
立即执行
微任务
同步的立即执行函数
generator
交出函数的执行权
调用 Generator 函数,会返回一个内部指针
next 方法的作用是分阶段执行 Generator 函数
流程不方便管理
async/await
好
异步操作的同步写法
坏
反设计
容易引起性能问题
async返回一个promise
await让出线程,跳出async函数体
Generator/function* 来实现
await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码。
Observable
事件循环
执行一个宏任务(栈中没有就从事件队列中获取)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
上下文
作用域链
本质
是指向变量对象的指针列表
变量对象
arguments
this
局部属性和方法
定义
每个函数都有自己的执行环境
当代码在一个环境中执行时,会创建作用域链
作用
保证对执行环境的所有变量和函数的有序访问
链
前端
当前代码所在环境的的变量对象
下一个变量,来自外部执行环境
最外层为全局执行环境
作用域链的尽头
node
global
web
window
变量搜索
静态作用域
变量对象
变量 (var, 变量声明);
函数的形参
函数声明 (FunctionDeclaration, 缩写为FD);
this
this是面向对象的表示
通过对象调用
其它
window
本质
this引用的是函数据以执行的环境对象
执行环境
全局执行环境
创建
当执行流进入一个函数时,函数的执行环境就会被推入环境栈中
销毁
在函数执行完之后,栈将其环境弹出,该环境被销毁
定义
每个执行环境都有一个与之关联的变量对象
环境中定义的所有变量和函数都保存在这个对象中
函数执行环境
函数调用时时
函数入栈
创建执行环境
创建作用域链
闭包
定义
函数和其相关引用对象组成的实体
闭包原理
从scheme语言借鉴来
基础
词法作用域
函数的变量作用范围可以超越创建的它的环境
在一些语言中,函数可以嵌套函数,当内部函数引用了外部函数的变量时,就有可能会形成闭包
由于有引用,不会被垃圾回收
弊端
内存占用过多
应用场景
模仿块级作用域
settimeout 拿到正确的值
创建私有变量
封装相关的功能集
模块化
jquery
设计单例模式?
惰性求值?
原型
两方面
对constructor模式的改善
对constructor模式的改善
避免重复定义
设计思想
JS的设计思想
不同于面向类,基于原型的语言是对实例友好的
实现继承
铁三角
构造函数
prototype指向原型对象
constructor指向构Function
原型对象
constructor指向构造函数
prototype指向原型的原型
实例
prototype指向原型对象
constructor指向构造函数
组合继承?
读写
读
先遍历自身的属性,如果没有一层层往上层寻找
写
如果原型存在该属性,则对该实例自身创建属性
ES6
let
暂时性死区
存在,但是不让使用
所以提前使用会报错
const
块级作用域
=>
解构
module
和CMD的区别
ES6
静态分析
引用方式
异步
Set
map
Object.observer()
symbol
不可改变且唯一的
以被用做对象属性的键
对原始数据类型的隐式对象包装器。
可以用来避免被覆盖
模板字符串
数组判断
Object.prototype.toString.apply([]) === "[object Array]"
[].constructor === Array
[] instanceof Array === true
Array.isArray([])
for-in for-of
for-in
循环对象&数组
循环只遍历可枚举属性
循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用propertyIsEnumerable)
for-of
循环数组
ES6新特性
不会循环对象的key,只会循环对象的value
遍历实现iterator接口
箭头函数
比函数表达书更简洁
没有this和arguments
复制对象
for-in
object.assign()
浅拷贝
JSON.parse(JSON.stringify(obj))
方法不能用于复制用户定义的对象方法
不能用于复制循环引用对象。
展开操作符(…)
浅拷贝
自实现
类型判断
Object.prototype.toString.call('')
事件阻止
阻止传播
event.Propagation()
W3C
event.cancleBubble()
IE
默认事件
event.preventDefault()
W3C
return false
原生JS事件
阻止默认行为
jQuery
阻止默认行为
阻止冒泡
W3c
e.returnValue = false
IE
iterator接口?
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
各种数据结构,提供一个统一的、简便的访问接口
数据结构的成员能够按某种次序排列
供for...of消费
编解码
escape
已从Web 标准中删除
对字符串进行编码,让计算机可以读取
编码集合
除
ASCII 字母和数字
ASCII 标点符号 - _ . ! ~ * ' ( )
encode
encodeURI
把字符串作为URI进行编码
目的是对 URI 进行完整的编码
编码集合
除
非转义字符
字母 数字 - _ . ! ~ * ' ( )
保留字符
; , / ? : @ & = + $
数字符号
#
encodeURIComponent
编码集合
除
字母 数字 - _ . ! ~ * ' ( )
;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号
十六进制的转义序列
decode
docodeURI
decodeURIComponent
类型化数组
通用的、固定长度的二进制数据缓冲区
JS开始执行时机
window.load
必须等待网页中所有内容加载完毕后才能执行
$(document).ready
dom结构绘制完毕后开始执行
封装了ondomcontentready、ondomcontentloaded
HTTP
cookie和session
cookie
服务器在本地机器上存储的小段文本
只能保管ASCII字符串
受浏览器安全策略限制
而Cookie保管在客户端,不占用服务器资源
session
服务器端的机制
任何类型的数据
Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险
Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存
基本概念
请求头
request header
响应头
response header
状态码
分类
1xx
信息响应类
2xx
处理成功响应类
3xx
重定向响应类
4xx
客户端错误类
400
客户端有语法错误,不能被服务器理解
401 未授权
403 拒绝提供服务
404
资源不存在
5xx
服务端错误
解决了什么问题
报文
是什么
承载多个请求参数的数据
报文格式
一次http完整的过程
输入网址
根据DNS,将域名解析为IP地址
建立TCP连接
三次握手
客户端发送报文
服务端应答
服务端返回状态码和请求体
关闭TCP连接
Accept - Encoding的作用,和性能有关系
对body部分进行编码,达到压缩的目的
编码类型
gzip
好处
节省空间
弊端
JPEG这类文件用gzip压缩的不够好
compress
deflate
zlib
请求方式
get和post区别
同
TCP链接
底层是TCP/IP
GET和POST能做的事情是一样的
定义
get
Get是向服务器发索取数据的一种请求
post
Post是向服务器提交数据的一种请求
不同
长度
get
无长度限制
但是浏览器会对URL厂区做出限制,2000多个字符
post
无长度限制
大多数服务器最多处理64K大小的url
字符
get
ASCII字符
post
没有限制
编码
get
application/x-www-form-urlencoded
post
POST支持多种编码方式
安全
get
GET参数直接暴露在URL上
post
POST参数在HTTP消息主体中
不会被保存在浏览器历史
缓存
get
请求会被浏览器主动缓存
post
POST不会
浏览器
GET请求参数会被完整保留在浏览器历史记录里
而POST中的参数不会被保留
建立过程?
产生一个TCP数据包
浏览器会把http header和data一并发送出去,服务器响应200(返回数据)
产生两个TCP数据包
浏览器先发送header,服务器响应100 continue
浏览器再发送data,服务器响应200 ok(返回数据)
https://zhuanlan.zhihu.com/p/25028045
https://www.zhihu.com/question/20552352
请求类型
get
post
创建
put
更新
delete
head
仅仅返回相应的头部,没有具体的响应体。它也不会对服务器造成其他影响
TRACE
options
OPTIONS允许客户端请求一个服务所支持的请求方法。它所对应的响应头是Allow,它非常简洁地列出了支持的方法。下面为服务端成功处理了OPTIONS请求后,响应的内容:
Allow: HEAD,GET,PUT,DELETE,OPTIONS
发生时机?
connect
用途?
websocket
异步请求和同步请求的区别
异步请求
并行处理
不等待
同步请求
顺序处理
等待
TCP/IP
协议集
应用层
传输层
网络层
网络访问层
三次握手
1 客户端到服务器
等待确认
2 服务器告诉客户端,收到消息,进入等待状态
3 客户端收到消息,发送确认包
然后,再传递消息
断开连接时服务器和客户端均可以主动发起断开TCP连接的请求
四次分手
客户端提出分手请求
服务端收到请求,关闭连接
并提出反方向关闭请求
客户端对服务端请求确认,双方向的关闭结束
http2
多路复用
相同域名请求通过同一个TCP链接并发完成
Hpack头压缩
二进制传输
1.x为文本格式
服务端推送
解决队头阻塞问题
帧
流
vs 1.x keep alive
1.x 串行传输
https?
证书颁发机构CA
https的信任基于预先安装在浏览器中的证书颁发机构
我信任证书颁发机构我应该信任的
HTTPS报文中的任何东西都被加密,包括所有报头和荷载。
和http的差异
端口
http
默认80端口
https
默认443端口
加密
对称加密
非对称加密
中心化加密
去中心化加密
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/74
优化
性能优化
原则
选择合适的衡量指标、测试用例、测试环境,找到瓶颈
度量
首次有效渲染
重要渲染时间
可交互时间
输入响应
不要过早优化
忌过度优化
性能优化是持久战
方向
语言本身
css
嵌套
合理使用硬件加速
少用高消耗属性
calc
shadow
js
语法
针对JIT的优化
隐藏类
WebWorker
框架
网络
分类
缓存技术
负载均衡
压缩
优化协议(HTTP,HTTP2.TCP/IP)
CDN
减少HTTP请求为何能优化速度
构建
压缩
分包
tree shaking
aot
并行处理
容器类优化
引擎优化
Wasm
整体结构优化
RN
fluter
混合应用
Hybrid
小程序
性能优化
页面加载链路优化
网络
CDN
HTTP请求数量
压缩
资源
分包
压缩
懒加载
缓存
热加载&离线包
首屏
首屏处理
外壳处理
拆分过程,并行处理
runtime优化
容器
WKWebview
V8
内联类
wasm
RN
canvas
webgl
硬件加速
语言层面
CSS
JS
框架层面
视觉
动画
交互
避免重排重绘
fastclick
解决问题
300ms延迟
原因
移动浏览器存在双击缩放或双击放大操作
第一次点击之后,系统需要等待300ms,以判断用户是否再次点击了屏幕
事件发生顺序
touchstart
touchmove
touchend
click
解决方法
禁用缩放
user-scalable=no
但同时也禁用了双指缩放操作
更累默认视口宽度
<meta name="viewport" content="width=device-width"></code>
仍可进行双指缩放操作
指针事件
pointerdown事件
css touchaction: none
是否触摸操作会触发用户代理的默认行为
zepto tap
document
touch事件
计算时间和位置差
fastlick
监听touchend
发出自定义click事件
把原来的click事件阻止掉
方案
自适应方案
响应式布局
通过媒体查询
viewport缩放
简单、高效
rem布局
动态设置根元素font-size,等比缩放元素大小
lazyimage
图片先用占位图表示,属性放到data里面
页面加载完成后,监听窗口滚动,
当图片出现在视口内,再赋予真实的地址
安全
DOS攻击
XSS攻击与防御
含义
跨站脚本攻击
方法
恶意将未经过滤的代码植入到页面中
分类
反射性
URL到页面
持久型
数据库
避免
常见符号编码转换
& < > " ' /
对诸如<script>、<img>、<a>等标签进行过滤
HttpOnly
避免cookie劫持
HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等,所需要的转义规则不一致。 业务 RD 需要选取合适的转义库,并针对不同的上下文调用不同的转义规则。
CSRF攻击
跨站请求伪造
攻击者盗用了用户的身份,以用户的名义发送恶意请求
在不同的domain下,攻击者却能为造出”用户本人发出的request“
避免
关键请求使用验证码或者token机制
验证码
在HTTP 头中自定义属性并验证
Cross Site
验证 HTTP Referer 字段
具体来说就是服务器每次返回客户端页面的时候,在页面中埋上一个token字段
SameSite
参考
https://blog.techbridge.cc/2017/02/25/csrf-introduction/
HTTP劫持与对策
https
浏览器
渲染过程
JS触发reflow?
JS
影响到DOM变化
Style
根据css计算变化后的dom样式
layout
计算每个 DOM 元素最终在屏幕上显示的大小和位置
Paint
为每个dom填充像素
本质上就是填充像素
一个DOM的所有可是效果
这个绘制过程是在多个层上完成的。
Composite
渲染层合并
在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上
完成绘制之后,浏览器会按照所有层顺序,合理的合并成一个图层,显示在屏幕上
某些特殊的渲染层会被认为是合成层(Compositing Layers),合成层拥有单独的 GraphicsLayer,
扩展
某些特殊的渲染层会被认为是合成层(Compositing Layers),合成层拥有单独的 GraphicsLayer,而其他不是合成层的渲染层,则和其第一个拥有 GraphicsLayer 父层公用一个。
每个 GraphicsLayer 都有一个 GraphicsContext,GraphicsContext 会负责输出该层的位图,位图是存储在共享内存中,作为纹理上传到 GPU 中,最后由 GPU 将多个位图进行合成,然后 draw 到屏幕上,此时,我们的页面也就展现到了屏幕上。
http://taobaofed.org/blog/2016/04/25/performance-composite/
层压缩
原因
大量合成层来,而每个合成层都要消耗 CPU 和内存资源,岂不是严重影响页面性能
事件模型
DOM0级模型
事件不会传播,即没有事件流的概念
btn.onclick = fun;
DOM2级模型
W3C标准模型
三个阶段
捕获
目标
冒泡
兼容问题
WebGL渲染的过程?
缓存策略
分类
DNS缓存
CDN缓存
浏览器缓存
强缓存
cache-control
no-cache
max-age=<seconds>
expires
协商缓存
Last-Modify
ETag
同源策略
定义
限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制
协议,端口(如果有指定)和域名
web语义化
使用恰当语义的html标签、class类名等内容,让页面具有良好的结构与含义,从而让人和机器都能快速理解网页内容。
线程
含义
程序执行中一个单一的顺序控制流程
为什么浏览器是单线程设计
如果JavaScript是多线程的方式来操作这些UI DOM,则可能出现UI操作的冲突
浏览器中的线程
界面渲染线程
GUI 渲染线程 与 JavaScript引擎线程互斥
javascript引擎线程
Http请求线程
定时触发器线程
浏览器事件触发线程
进程
含义
代表CPU所能处理的单个任务
有单独的内存区域
和线程的关系
一个进程由一个或多个线程组成
线程是一个进程中代码的不同执行路线
Chrome浏览器使用多个进程来隔离不同的网页
HTML加载过程?
输入地址,返回HTML
加载DOM
遇到body标签
加载并渲染DOM
浏览器遇到dom元素时,正常顺序加载,边加载边渲染
内联CSS
浏览器继续加载,但渲染被阻塞
生成新的CSS Rule Tree
生成后重新渲染界面
内联Javascript
DOM的加载和渲染同时被阻塞
由于JavaScript有可能会更改DOM Tree和Render Tree,因此同时被阻塞
外联Javascript
DOM的加载和渲染同时被阻塞
render tree
layout
文档碎片?
内存
合成一个DOM?
内存管理
概念
像C语言一般都有自己的内存管理接口,JS创建变量时分配内存,而不再使用时再释放内存。
方法
标记清除
从根部开始遍历,找出不再使用的变量
阶段
初始阶段
标记阶段
JS会停止运行
清楚阶段
V8
增量标记
引用计数
优势
算法简单
释放时间快
劣势
循环引用问题
对计数要求高
不能并行计算
堆内存
全局变量
对象的引用
事件
定时器
堆和栈的区别
堆
动态分配的内存,大小不定也不会自动释放
JS中引用类型占据空间大、大小不固定,栈内存中存放地址指向堆内存中的对象。按引用访问
栈
自动分配的内存空间,由系统自动释放
基本类型占据空间小、大小固定,值保存在栈空间。按值来访问
内存泄漏实例?
内核
KHTML
Webkit
是排版引擎
01年开始苹果
组件
JS Core
webcore
Drosera
调试工具
组成
渲染引擎
HTML解释器
CSS解释器
布局
JS引擎
JS 引擎
源代码 –> 抽象语法树 –> 字节码(跨平台) –> JIT –> 本地代码
Blink
blink
13年,webkit的分支
V8
框架
Angular
脏值检查
数据何时变化
用户输入
请求服务端数据
定时事件
监听变化
使用zone.js Monkey patch的方式,监听所有异步事件
变化检测
新旧数据对比
angular改善的脏检查
组件树
每个组件都有自己的变化检测器
变化检测器树
数据流自上而下
高效
可预测
相比之下,AngularJS采用的是双向数据流,错综复杂的数据流使得它不得不多次检查,使得数据最终趋向稳定。理论上,数据可能永远不稳定。AngularJS给出的策略是,脏检查超过10次,就认为程序有问题,不再进行检查。这个10,我不知道它的给出依据是什么,也许是个经验值吧。
变化检测对象
定制变化检测
DI
目标
控制反转
好处
降低代码之间的耦合度
每个对象都需要获取与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实
实现方式
依赖注入
Injector会自动帮你将需要的依赖注入到类的构造器里,并返回这个类的实例
使用的三个技术
reflect-metadata
typescript
Decorator
数组绑定
生命周期
ngOnChanges
ngOnInit
ngDoCheck
ngAfterContentInit
在外来内容被投影到组件中之后/投影组件内容的变更检测之后调用
ngAfterContentChecked
ngAfterViewInit
初始化完/检测变更完组件视图及其子视图之后调用。
ngAfterViewChecked
ngOnDestroy
Vue
数据绑定
实现原理
数据劫持的方式来做数据绑定
方法
Object.defineProperty()
getter
setter
notify
监听变化
Watcher
Observer
React
本质
规范
接口
数据绑定
数据变化
setState()通知变化
数据更新
virtual DOM
原理
本质上就是在 JS 和 DOM 之间做了一个缓存
会跟踪每一个组件的依赖关系
弊端
如果你的应用中,交互复杂,需要处理大量的UI变化,那么使用 Virtual DOM 是一个好主意。如果你更新元素并不频繁,那么 Virtual DOM 并不一定适用,性能很可能还不如直接操控 DOM。
好处
diff
抽象
diff算法
react渲染机制、key的用途
生命周期
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillMount
componentDidMount
componentWillReciveProps
componentWillUnmout
render
state和props
state是做为状态管理
而props相当于api,由外界传入
问题
setState
this.updater
合并旧state
放进state队列,等待更新
集齐一批需要更新的组件然后一起更新
updater
react-dom
render
它是异步的
没有脏值检查?
大三框架的比较
同
都以组件化为核心
都利用了MVVM设计模式
都可以完成各式的前端项目,只是方式和灵活度不同
不同
核心思想
react
对view层的抽象定义,规范化、接口化
vue
以组件化和MVVM为核心,小而轻
angular
利用用先进 的设计模式和思想,提供系统化的解决方案,大而全
适合工程
react
最适合抽象和跨端项目
中小型项目vue更合适,只是vue生态不及react
vue
中小型工程
angular
中大型工程
独特的优势
react
极度抽象,跨平台
vue
渐进式增强,对小项目非常友好
angular
系统化、优秀的设计模式和思想
内置的优化解决方案
MVC
单例
观察者
数据流
依赖翻转
typescript
CLI
缺点
react
过度自由
太过抽象
vue
学习者的姿态
angular
小项目收益低
学习曲线高、概念多、难以理解
MVVM和Virtual Dom比较
初始渲染:Virtual DOM > 脏检查 >= 依赖收集
小量数据更新:依赖收集 >> Virtual DOM + 优化 > 脏检查(无法优化) > Virtual DOM 无优化
大量数据更新:脏检查 + 优化 >= 依赖收集 + 优化 > Virtual DOM(无法/无需优化)>> MVVM 无优化
架构
三种软件架构
目标
面向GUI编程领域
分类
MvvM
软件架构模式
软件逻辑和数据逻辑分离开来
视图模型是暴露公共属性和命令的视图的抽象
包含
模型
代表真实状态的数据模型
视图
视图模型
暴露公共属性和命令的视图的抽象
绑定器
声明性数据和命令绑定
绑定器使开发人员免于被迫编写样板式逻辑来同步视图模型和视图
MVC
模型
控制器
视图
MVP
对MVC的变种
Presenter 可以理解为松散的控制器,其中包含了视图的 UI 业务逻辑
实践
典型项目
项目
数据配置平台
身份
主导者
设计者
开发者
系统
数据配置
粒度划分
空间
项目
项目
回滚
权限
用户管理
日志
良好的交互
技术选型
angular
node.js
mongodb、mysql
php + mysql
遇到的问题
配置形式
配置的表达形式
json
针对每个业务进行可视化开发
策略
解决方案
json和可视化自动转换方案
操作
研发使用json进行数据编辑
业务方使用可视化进行编辑
原理
正向
json string
monaco编辑器
转成comment json
包含注释信息的json
解析comment json
取出数据和标题
转成angular form reactive表达形式
将form reactive转化为视图
针对每种数据类型做优化
数字
字符串
布尔型
php接口逻辑和压力
自动化测试脚本
压力测试
每天上亿的流量
如何解决问题
理解目标、找到瓶颈
监控和优化案例
工程化
WebPack打包原理
require
根据node的规范封装的模块化
名词
loader
模块转换器
plugin
自定义打包流程
过程
准备
加载所有插件
确定入口文件
编译
递归寻找模块依赖
调用loader对模块进行编译
资源输出
输出chunk文件
软
未来工作计划
为什么选择前端
平时关注新技术吗?哪些渠道
项目选型
缺点
跳
简单算法
数组去重
Array.from(set)
排序后去重
filter
双层循环
频率控制
防抖 debounce
含义
高频事件
n秒内只执行一次
如果n秒内再次被触发,则重新触发时间
实现思路
每次事件触发后,都取消原来的延时处理方法
节流 throttle
含义
在n秒内忽略随后发出的源值
实现思路
每次触发事件时,都判断当前是否有延时函数
数组扁平化
Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})
高级应用
状态管理
redux
JavaScript 状态容器,提供可预测化的状态管理
动机
state过多,来源复杂
服务器数据
缓存
路由
让state的变化可预测
好处
一个action对应了一个完整的应用状态
历史记录功能
易于测试
reducer是纯函数
概念
action
行为、指令
store的唯一数据来源
reducer
响应action,并发送到store
store状态容器
mobx
rxjs
Pendding
HTML加载过程?