前 另外,如果要改变阻塞模式,可以使用 defer 与 async,详见:这篇文章 **4、布局与绘制** 确定渲染树种所有节点的几何属性,比如:位置、大小等等,最后输入一个盒子模型,它能精准地捕获到每个元素在屏幕内的准确位置与大小。 然后遍历渲染树,调用渲染器的 paint() 方法在屏幕上显示其内容。 **5、合并渲染层** 把以上绘制的所有图片合并,最终输出一张图片。 **6、 回流与重绘** **回流(reflow)** 当浏览器发现某个部分发现变化影响了布局时,需要倒回去重新渲染,会从 html标签开始递归往下,重新计算位置和大小。整编:微信公众号,搜云库技术团队,ID:souyunku reflow基本是无法避免的,因为当你滑动一下鼠标、resize 窗口,页面就会产生变化。 **重绘(repaint)** 改变了某个元素的背景色、文字颜色等等不会影响周围元素的位置变化时,就会发生重绘。 每次重绘后,浏览器还需要合并渲染层并输出到屏幕上。 回流的成本要比重绘高很多,所以我们应该尽量避免产生回流。 比如: ``` display:none 会触发回流,而 visibility:hidden 只会触发重绘。 ``` 7、JavaScript 编译执行 **大致流程**  **可以分为三个阶段:** 1、词法分析 JS 脚本加载完毕后,会首先进入语法分析阶段,它首先会分析代码块的语法是否正确,不正确则抛出“语法错误”,停止执行。 **几个步骤:** **分词**,例如将 vara=2,,分成 var、 a、 =、 2这样的词法单元。 **解析**,将词法单元转换成抽象语法树(AST)。 **代码生成**,将抽象语法树转换成机器指令。*2、预编译 JS 有三种运行环境: 1、全局环境 2、函数环境 3、eval 每进入一个不同的运行环境都会创建一个对应的执行上下文,根据不同的上下文环境,形成一个函数调用栈,栈底永远是全局执行上下文,栈顶则永远是当前执行上下文。 创建执行上下文 **创建执行上下文的过程中,主要做了以下三件事:** 创建变量对象 - 参数、函数、变量 建立作用域链 - 确认当前执行环境是否能访问变量 确定 This 指向 3、执行 **JS 线程**  虽然 JS 是单线程的,但实际上参与工作的线程一共有四个: ``` 其中三个只是协助,只有 JS 引擎线程是真正执行的 ``` **JS 引擎线程:** 也叫 JS 内核,负责解析执行 JS 脚本程序的主线程,例如 V8 引擎 **事件触发线程:** 属于浏览器内核线程,主要用于控制事件,例如鼠标、键盘等,当事件被触发时,就会把事件的处理函数推进事件队列,等待 JS 引擎线程执行。整编:微信公众号,搜云库技术团队,ID:souyunku **定时器触发线程:** 主要控制 setInterval和 setTimeout,用来计时,计时完毕后,则把定时器的处理函数推进事件队列中,等待 JS 引擎线程。 **HTTP 异步请求线程:** 通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。 **注:浏览器对同一域名的并发连接数是有限的,通常为 6 个。** **宏任务** 分为: 1、同步任务:按照顺序执行,只有前一个任务完成后,才能执行后一个任务 2、异步任务:不直接执行,只有满足触发条件时,相关的线程将该异步任务推进任务队列中,等待JS引擎主线程上的任务执行完毕时才开始执行,例如异步Ajax、DOM事件,setTimeout等。 **微任务** 微任务是ES6和Node环境下的,主要 API 有:Promise, process.nextTick。 微任务的执行在宏任务的同步任务之后,在异步任务之前。   **代码例子** ```java console.log('1'); // 宏任务 同步 setTimeout(function() { console.log('2'); // 宏任务 异步 }) newPromise(function(resolve) { console.log('3'); // 宏任务 同步 resolve(); }).then(function() { console.log('4') // 微任务 }) console.log('5') // 宏任务 同步 ``` 以上代码输出顺序为:1,3,5,4,2
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69956585/viewspace-2843587/ ,如需转载,请注明出处,否则将追究法律责任。