浏览器渲染原理之js引擎

BOM与DOM

  • BOM:浏览器对象模型,用来设置浏览器的属性、行为,提供了独立于内容而与浏览器窗口进行交互的对象。描述了与浏览器进行交互的方法和接口,可以对浏览器窗口进行访问和操作。
  • DOM:文档对象模型,用来设置文档中标签的属性,是针对XML的基于树的API。描述了处理网页内容的方法和接口,是HTML和XML的API,DOM把整个页面规划成由节点层级构成的文档。DOM本身是与语言无关的API,

<script>标签

  • 通过<script>标签可以直接将js代码嵌入网页。
  • <script>标签 可以以指定加载外部脚本
  • <script>标签 设置 integrity属性,写入该外部脚本Hash前面,可以验证脚本一致性,防止攻击者篡改外部脚本,
  • <script>标签加载外部脚本时,浏览器会暂停页面渲染
  • <script>标签应该放在页面底部,避免外部脚本加载时间过长造成页面阻塞问题。
  • <script>标签 脚本执行的属性是按照在页面出现的顺序决定的。
  • <script>标签 defer属性告诉浏览器等DOM加载完成后在执行脚本,浏览器解析过程中 会并行下载带有<script>标签 defer属性的脚本,同时继续解析HTML网页,浏览器完成解析HTML网页后,在执行下载的脚本。
  • <script>标签 async 属性,使用另一个进程下载脚本,下载时不会阻塞渲染 ,浏览器解析过程中解析过程中会并行下载带有<script>标签asnc属性的脚本,同时继续解析HTML网页,当脚本下载完成后,浏览器粘贴解析HTML网页,开始执行下载的脚本,脚本执行完毕后,浏览器回复解析HTML网页。
  • 浏览器默认采用HTTP协议写在脚本,如果希望,根据页面本身的协议来决定加载协议,可以这样<script src="//user.js"></script>

js虚拟机

  • 即时编译(JIT),即字节码只在运行时编译,并将编译结果缓存。
  • 有的js引擎省略字节码编译步骤,直接编译成机器码(chrome v8引擎),js虚拟机不完全基于字节码,有部分基于源码,利用JIT编译器直接将源码编译成机器码运行,就省略了字节码步骤。
  • 字节码不能直接运行,而是运行在虚拟机上,一般虚拟机称为js引擎。

js 单线程模型

  • js是单线程运行的(js可以修改DOM,涉及多个线程对DOM操作,会引发更为复杂的概念,为了避免复杂性,js被设计为单线程)。
  • H5中,js被允许创建多个线程,但子线程收主线程控制,且不得操作DOM,
  • 单线程的模型,当任务队列阻塞时,会使得浏览器失去响应,为此JS 设计者采用一种机制,将处于等待的任务挂起,先运行排在后面的任务,当挂起的等待任务有了结果,再回过头执行挂起的任务,这种机制被称之为Event Loop。

Event Loop 和消息队列

  • Event Loop 是一种执行模型,指的是一种内部循环,用来一轮又一轮的处理消息队列中的消息,即执行对应的回调函数。也可以理解为动态更新的消息队列本身。
  • 所有任务分为同步任务和异步任务,同步任务指的是js执行进程按照顺序执行,只有前者任务执行完毕,后者任务才可以执行。异步任务指的是,不进入js进程,而是进入任务队列(task queue)任务,只有任务队列通知主进程某个异步任务可以执行了,该任务才会进入js进程。

宏队列和微队列

  • 宏队列(macrotask) tasks,一些异步任务的回调会依次进入macro task queue 等待调用。
setTimeout
setInterval
setImmediate (Node独有)
requestAnimationFrame (浏览器独有)
I/O
UI rendering (浏览器独有)
  • 微队列 (microtask ) jobs,另一些异步任务的回调会依次进入 micro task queue,等待后续被调用,
process.nextTick (Node独有)
Promise
Object.observe
MutationObserver
  • 宏队列一次从队列中取一个任务执行,然后再去微任务队列microtask queue中依次取出执行,当微任务队列执行完后,会执行UI redering(执行完所有微任务后,下一个宏任务之前)。
  • 微任务队列全部执行完,再去宏任务队列中取第一个任务执行。
Stack Queue: [任务栈], //调用栈

Macrotask Queue: [宏任务的回调函数],//宏队列

Microtask Queue: [微任务的回调函数],// 微队列
console.log(1);

setTimeout(() => {
  console.log(2);
  // callback1 ( 1.入宏队列)
  Promise.resolve().then(() => {
   // callback4 ( 4.入微队列)
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  // callback2 ( 2.入微队列)
  resolve(5)
}).then((data) => {
  console.log(data);
})

setTimeout(() => {
 // callback3 ( 3.入宏队列)
  console.log(6);
})

console.log(7);

// 全部执行script后,调用栈和宏队列、微队列情况
Stack Queue: [console]
Macrotask Queue: [callback1, callback3]
Microtask Queue: [callback2]

打印结果:
1
4
7
1.先执行微队列callback2 => 1475
Stack Queue: [callback2]
Macrotask Queue: [callback1, callback3]
Microtask Queue: []
2.接着执行第一个宏队列callback1 =>14752
Stack Queue: [callback1]
Macrotask Queue: [callback3]
Microtask Queue: []
3.接着微任务进入微队列  => 14752
Stack Queue: [promise]
Macrotask v: [callback3]
Microtask Queue: [callback4]
4.执行微队列callback4 => 147523
Stack Queue: [callback4]
Macrotask Queue: [callback3]
Microtask Queue: []
5.最后执行第二个宏队列 callback3 =>1475236
tack Queue: [callback3]
Macrotask Queue: []
Microtask Queue: []
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值