浏览器的渲染进程是多线程的:
1.GUI渲染进程,渲染界面,解析HTML,CSS,构建DOM树。GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起
由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。
渲染过程:
①解析HTML
②解析css
③布局render树(DOM和CSSOM结合)
④绘制render树,绘制页面信息
⑤渲染完毕
DOMContentLoaded是指所有的DOM加载完成,不包括样式,图片
onload触发时,页面渲染完毕,所有图片样式DOM都已经加载完
2.JS引擎线程,处理JS脚本。单线程,如果多线程的话,两个线程同时操作一个DOM,一个更新,一个删除,就不好操作。
3.事件触发线程,控制事件循环
4.定时触发器线程,计时触发定时
5. 异步http请求线程
事件循环
JS中分为两种任务类型:macrotask(宏任务)和microtask(微任务)
每次执行栈执行的代码就是一个宏任务。每次宏任务结束会对页面重新渲染。再继续执行下一个宏任务
微任务是宏任务结束立即进行的任务,在渲染之前
macrotask:主代码块,setTimeout,setInterval
microtask:Promise
运行机制:先执行宏任务,过程中遇到微任务会放进微任务队列,当前宏任务完成后,检查微任务列表里是否有微任务,如果有的话,依次执行所有微任务,然后浏览器渲染。再进行下一个宏任务
JS事件分级
1.HTML事件处理程序
直接在HTML元素中定义事件处理。列入<input type="text" οnclick="change()"/>
这样在函数内部有一个局部变量event,代表着事件对象;
在元素中写的事件函数里this代表事件目标元素,比如change(this)
2.DOM0级事件处理程序,函数内部有event,this
在JS中将函数赋给元素的事件属性,例如:
node.οnclick=function(){console.log(this)}
this代表元素对象。 注意,不能用箭头函数!!否则this失灵(这是因为箭头函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象)
3.DOM2级事件处理程序,函数内部有event,this
addEventListener(事件名,function(){},boolean(在捕获还是冒泡阶段处理)) removeEventListener()
处理函数中this表示该元素对象
在remove时,如果当初用的是匿名函数则无法删除事件
event.preventDefault()阻止事件的默认行为
event.stopPropagation()阻止事件冒泡。如果父元素也有事件,需要阻止子元素的事件冒泡,防止触发两次事件
JS闭包
有权访问另一个函数作用域内变量的函数都是闭包,就是能在函数外部访问函数内的局部变量。
应用场景:1.实现私有属性,实现封装