这是在腾讯课堂白嫖 京程一灯 的视频直播课。课程网址如下: 面试必备:三步带你吃透浏览器原理,如果你对视频感兴趣可以联系客服1块钱购买。
《三步带你吃透浏览器原理》[ ] 书籍 [ ] 讲座 [x] 视频 | |||
---|---|---|---|
作者 | 京程一灯 | 出版社 | |
阅读日期 | 2020年2月 | 更新日期 | 2020年2月 |
相关链接 | 面试必备:三步带你吃透浏览器原理 | 备注 | 三节直播课 |
课程分三节:
- 浏览器架构及原理
- js执行机制及v8原理
- 浏览器页面及安全知识要点
现在做个笔记如下。
1. 浏览器架构及原理
提到的一些零碎无关知识点:
- webGL编程指南
- for in of 元编程
- 微任务 宏任务
- 单进程
- 协程 generator
1.1 前端网络
1.1.2 HTTP请求
输入网址发生了什么。这里也有其他文章更仔细完整。
- 构建请求,一般是 HTTP1.1
- 查找缓存,强缓存、协商缓存304
- 准备ip和端口:DNS
- 等待TCP连接。这里同一域名同时最多6个TCP连接
- 建立TCP连接。也就是三次握手
- 发送HTTP请求,HTTP的组成:请求行、请求头、请求体
- 服务器响应。响应行状态码、响应头、响应体
- 断开连接。或者keep-alive
常规流程。收获不大。
1.2 HTTP历史和未来
这里看https://www.yuque.com/xinbao37/high_performance/about-network-protocol
1.3 浏览器拿到了返回数据
https://www.yuque.com/xinbao37/high_performance/page-render
2 js执行机制及v8原理
学技术很孤独,剩者为王,靠坚持。
最好的是凭借兴趣。
2.1 js执行机制
理解执行上下文
2.1.1 变量提升
看这段代码:
showName()
console.log(myName)
var myName = 'xx'
function showName(){console.log('yy')}
执行之前会把 代码编程类似下面的样子
var myname = undefined // var 提升
function showName(){xxx} // function 提升
showName()
console.log(myname)
myname = 'xxx'
可以这么想,但实际上不是这么做,位置是不会改变的。编译阶段会被引擎放入内存。
js源码 — 编译 — 执行。
虽然都提升,但function优先
请看下面这个变态的题目:
debugger;
alert(a)
a()
var a=3
function a(){alert(10)}
function a(){alert(20)}
alert(a)
a=6
a()
// function a(){alert(20)} -- 20 -- 3 -- Error a is not a function
// 会变成这样:
// function 优先级大于 var
// 后面的大于前面的
function a(){console.log(20)}
alert(a)
a()
a=3
alert(a)
a=6
a()
调用栈 call stack
标准的es6写法:全局执行上下文 包含了
变量环境 + 词法环境 + outer + this
在es5中,(尤其是你不知道的js第一版上册) 包含了 VO,vo激活的过程,ao等
var a=2
function add(b,c){return b+c}
function addAll(b,c){
var d =10
var res = add(b,c)
return a+res+d
}
addAll(3,6) // 3+6+2+10=21
解析过程:
变量环境:
- a=undefined
- add = function(){} // 其实应该放入堆,堆的地址
- addAll = function(){}
调用栈 stack 先进后出
一步一步走,不断压栈。
块级作用域
- 为了避开变量提升,兼容var,引入了 let const
- 引入块级作用域,就有了词法环境。
作用域
程序中定义变量的区域,也决定这生命周期。
也就是变量和函数的可访问范围和生命周期。
es5时候只有 全局作用域 和 函数作用域 。
变量提升带来的问题
- 容易被覆盖掉
- 本该销毁的变量没有销毁
分析下面的代码执行:function foo(){
for(var i=0;i<3;i++){} // 提升
console.log(i)
}
foo()
注意var c
会提升,let会放入词法作用域
找a时候是这样找
来一个变态的题目,在es5中严格模式会报错。
let a=2
console.log(a)
{
console.log(a)
function a(){log1}
}
log(a)
bind 箭头函数没有原型 yield 协程
作用域链和闭包
每个执行上下文的变量环境中,都有一个外部引用,指向外部的执行上下文,这个外部引用称为 outer
,es5时候交 scope chian
闭包
原理是啥,是作用域链
debugger;
function foo(){
var myName = 'xx'
let test1 = 1
const test2 = 2
var innerBar = {
getName:function(){
debugger; // 控制台 local -- closure -- global
console.log(test1)
return myName
},
setName:function(v){
myName=v
}
}
return innerBar
}
var bar =foo()
bar.setName('x')
bar.getName()
this
动态执行。
这是es3版本。
栈空间和堆空间
原始数据类型是存在 栈空间 ,引用类型是存在 堆空间 的。
垃圾回收
编译器和解释器
源代码 — 词法分析 语法分析 — ast + 执行上下文 — 字节码 — 机器码
JIT 即时编译
字节码 — 是否有热点hot? — 没有热点就点火,有热点就涡轮增压Tubofan
消息对列和事件循环
EventLoop 底层是一个循环,引入了队列。
消息队列,先进先出:
- 输入事件 鼠标滚动 点击 移动
- 微任务
- 文件读写
- ws
- js定时器等
- js执行 解析DOM 样式计算 布局计算 css动画等
因此宏任务之间不光是js,也有渲染页面等。
每次宏任务中间,执行微任务。
宏任务
- 渲染事件 如解析DOM 计算布局 绘制
- 用户交互
- js脚本执行
- 网络请求 文件读写
微任务
主函数执行结束之后 — 微任务 — 宏任务结束之前。
3 浏览器页面及安全知识要点
- google性能优化
DOM树
DOM树如何生成,利用 HTML解析器。
有了响应头之后,会判断 content-type 是啥,如果是 text/html
就简单了。
- 如果是 html 文件
- 请求创建 渲染进程
- 网络进程和渲染进程建立共享数据的通道,一边放,一边读取 送给html解析器,解析为DOM
这里维护了一个 token栈,startTag压栈,endTag出栈,通过一个栈结构,维护了DOM树
js如何影响DOM
抽离。
CSS如何影响
CSS动画比js动画高效
一般是60Hz
paint处理完提交,交给合成线程
优化页面
- 加载阶段
- 减少关键资源个数,比如内联、defer
- 降低关键资源大小
- 降低关键资源的RTT次数,round-trip-time 一个往返的网络时间
- cdn
- 交互阶段
- 减少js执行时间,分割,使用sw
- 避免强制同步布局,尽量不要修改DOM时候查询一些值
- 合理使用css合成动画
- 尽量频繁的垃圾回收,临时变量等
浏览器安全
同源策略
XSS
攻击方式:
- 存储式攻击。用户输入的地方写入script标签
- 反射性攻击。恶意链接
- 劫持,wifi 运营商劫持。
解决办法:
- 转义
- 浏览器,限制非让么,上报
- cookie http only
CSRF
第三方获取登录态。
- cookie sameSite
- 验证referer
- csrf toekn
HTTPS
SSL/TLS 安全层。
不是很理解剩下的。
传密钥使用非对称加密,安全。传输数据使用对称加密,速度。
- 浏览器端:对称加密套件列表 + 加密套件列表 + client-random
- 服务器端:非对称加密套件+加密套件+service-random+公钥
- 保存公钥,生成随机数pre-master,然后利用公钥对pre-master加密,发送加密后
- 服务器拿出私钥,揭密pre-master数据