1、JS自定义事件
2、变量提升与暂时性死区
3、JS加载顺序
浏览器在解析html的时候,遇到script标签,就会暂停解析,如果script标签里是代码,则会先执行js,再继续解析html,如果是js文件,则会先加载js文件,然后执行js,再继续解析html
<html lang="en">
<head>
<script>
console.log("内联JS");
</script>
<script src="./demo.js"></script>
</head>
<body></body>
</html>
解析DOM => (加载JS)执行JS => 解析DOM
当JS文件过大执行时间过长时,就会阻塞页面的加载,导致页面长时间的空白,可以将script标签移至body底部,即使JS会阻塞之后的DOM解析,但是因为在底部,也不会产生太大的影响
defer
defer属性会使JS延迟到DOM解析完再执行,但是JS文件加载是和DOM解析同步执行的,当解析到script标签时开始加载
<html lang="en">
<head>
<script defer src="./demo.js"></script>
</head>
<body></body>
</html>
如果使用defer属性,可以将script标签写在head中,以便JS文件尽快加载,放置加载时间过长阻塞流程
async
async属性,会在JS加载完后立即执行JS,加载过程是和DOM解析同步执行的
<html lang="en">
<head>
<script async src="./demo.js"></script>
</head>
<body></body>
</html>
async的优先级高于defer,如果同时设置,defer将失效
esm
// a.mjs
import b from "./b.mjs"
import c from "./c.mjs"
<html lang="en">
<head>
<script type="module" src="./a.mjs"></script>
</head>
<body></body>
</html>
如果使用esm,则默认为defer,会先加载所有JS文件,然后在DOM解析完后执行
因为esm的依赖分析是静态的,在加载了a文件之后,还要分析a文件里通过import导入的其他依赖文件,只有这些文件都加载完成才能开始执行JS,根据esm的规则,会首先执行b文件,之后是c文件,最后是a文件
设置为async
4、DOMContentLoaded 与 load 事件什么时候被触发
DOMContentLoaded会在DOM解析完触发,load事件会在整个页面加载完触发,所以DOMContentLoaded总会先于load执行
在同步阻塞中,DomContentLoaded会在js执行完触发
使用了defer属性,DOMContentLoaded也会在js执行完触发
当使用async属性,DOMContentLoaded事件会在DOM解析完触发,事件触发与js的加载和执行没有关联,会出现事件已经触发但是js还未执行完的情况
5、浏览器的渲染与事件轮询的关系
6、回流和重绘
回流一定重绘,重绘不一定回流
回流:会引起元素位置尺寸内容变化的操作会引起回流,包括获取一些需要即时计算得到的值也会引起回流,包括offset、scroll、client
重绘:元素的样式的改变不影响其在文档流中的位置时,只会引起重绘,比如color等,重绘的成本比回流要小得多
避免频繁获取会引起回流的属性
动画元素可以使用定位使其脱离文档流
浏览器本身也有一些优化机制:
批处理:浏览器会收集多次dom操作合并为一次回流和重绘,而不是每次dom操作都进行回流和重绘,减少回流和重绘的次数
分层:将页面分层,独立渲染每个图层,每次dom操作只需要重绘单一图层,不需要整体回流
布局折叠:如果不断触发回流和重绘,浏览器会合并多次操作,尽量最小化这些操作,只执行必要的更改
7、浏览器渲染分层
8、为什么vite速度比webpack快
冷启动
webpack:在启动时,会根据入口文件,分析项目中的依赖关系,将项目打包成一个文件交给浏览器渲染,如果项目越大越复杂,生成的打包文件就越大,启动就会越慢
vite:浏览器支持esm特性,浏览器遇到内部的import引用时,就会自动发起http去加载对应模块,vite利用esm这个特性,在项目运行时,会首先使用esbuild进行预构建,将所有模块都转为esm,不需要对整个项目进行打包,而是在浏览器需要某个模块的时候,拦截浏览器发出的请求,根据请求按需编译,然后返回给浏览器,所以,首次启动会快很多
热更新
webpack:每次更新都要重新打包,即使增加了缓存机制,也没有太大改善 vite:每次更新使用ws通知浏览器重新发起请求,只对该模块进行重新编译然后进行替换,并且基于esm的特性,vite利用浏览器的缓存机制,对项目代码进行了协商缓存,对项目依赖进行了强缓存,提高了相应速度 在生产环境,vite还是会进行打包
9、Eslint 代码检查的过程
首先,需要为eslint配置一套规则
在eslint运行时,会将代码解析为ast抽象语法树,然后遍历,检查节点是否违反了规则
遍历完成,eslint会将问题分类并生成一份问题报告,根据配置的不同,问题可能会阻止构建或者被忽略