HTML DOCTYPE的含义?什么是HTML的标准模式与混杂模式?
doctype,HTML的文档类型声明,写在第一行,说明这个页面是用什么来编写的
HTML5有哪些语义化标签及特征?HTML元素有哪些分类与特性?
语义化标签可以让我们根据结构化的内容,选择合适的标签
- 对seo有利
- 代码可读性更好
- 标签上加上alt、title,方便一些其他设备进行解析,accessibility(可访问性),如盲人设备
如何检测浏览器是否支持HTML5特性?
- canvas
- video、audio
- 本地缓存的文件:localStorage、worker
- articel、footer、header
- form:calender、date
- esm(es module):模块化规范,可以在script代码里去import,而不是用require,script是不再需要type="moudle"属性了
检测方式:
(1)检查特定的属性和方法:
!!navigator.geolacation
!!window.localStorage
!!window.Worker
(2)创建一个元素,看看特定元素,有没有属性和方法
document.createElement('canvas').getContext()
document.createElement('video').canPlayType
(3)第三方库:
HTML中meta的作用?
meta标签的组成: meta标签共有两个属性,它们分别是http-equiv属性和name属性,不同的属性又有不同的参数值,这些不同的参数值就实现了不同的网页功能。
(1)name属性主要用于描述网页,与之对应的属性值为content,content中的内容主要是便于搜索引擎机器人查找信息和分类信息用的
<meta name="参数" content="具体的参数值">
参数主要有:
- Keywords(关键字):用来告诉搜索引擎你网页的关键字是什么
- description(网站内容描述):用来告诉搜索引擎你的网站主要内容
- robots(机器人向导):用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引
- author(作者):标注网页的作者
- generator:代表说明网站的采用的什么软件制作
- COPYRIGHT:代表说明网站版权信息
(2)http-equiv属性:相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容,与之对应的属性值为content,content中的内容其实就是各个参数的变量值
<meta http-equiv="参数" content="具体的参数值">
http-equiv属性主要参数:
- Expires(期限):可以用于设定网页的到期时间。一旦网页过期,必须到服务器上重新传输(必须使用GMT的时间格式)
- Pragma(cache模式):禁止浏览器从本地计算机的缓存中访问页面内容
- Refresh(刷新):自动刷新并指向新页面
- Set-Cookie(cookie设定):如果网页过期,那么存盘的cookie将被删除
- Window-target(显示窗口的设定):强制页面在当前窗口以独立页面显示,用来防止别人在框架里调用自己的页面
- content-Type(显示字符集的设定)
- content-Language(显示语言的设定)
- http-equiv="imagetoolbar":指定是否显示图片工具栏,当为false代表不显示,当为true代表显示
- Content-Script-Type:W3C网页规范,指明页面中脚本的类型
HTML的标签有哪些可以优化SEO?
-
保证页面是SSR的,SEO能抓取到页面内容
-
增加meta中相关属性,方便索引
<meta name="author" content="xxx.com"><meta name="description" content="xxx, xxx 系统"><meta name="keywords" content="xxx, xxx 系统"> -
使用语义化标签:title、meta、header、nav、article、aside、footer,以一些结构化的为主
DOM和BOM有什么区别?
JavaScript在浏览器环境下,一般由三部分构成 (1) ECMAScript核心:描述了JS的语法和基本对象 (2) DOM:文档对象模型,顶级对象是document,有一些API,可以操作文档
(3) BOM:浏览器对象模型,browser,顶级对象是window,有一些API,可以操作浏览器(浏览器屏幕)
- window.location:用于获取当前页面的URL,编写代码时不可使用window这个前缀
- window.navigator:包含有关访问者浏览器的信息,常用于导航,操作浏览器,编写代码时不可使用window这个前缀
- window.history:记录了浏览器的访问历史,为了保护用户隐私,对JavaScript访问该对象的方法做出了限制
如何实现移动端适配?
(1)百分比布局:也叫流式布局,效果:宽度自适应,高度固定;是一种比较老的解决方案,现在基本上是作为辅助使用
(2)Flex弹性布局:是一种浏览器提倡的布局模型,布局网页更简单、灵活、避免浮动脱标的问题,是目前比较流行的一种方式
(3)rem:等比缩放布局,rem是相对单位,相对于HTML标签的字号计算结果,是目前多数企业在用的解决方案,屏幕宽度不同,网页元素尺寸不同(等比缩放)效果
1rem=1html字号(基准根字号)大小;目前rem布局方案中,将网页等分为10份,HTML标签的字号为视口宽度的十分之一,如:设计稿为375px,1rem=1html字号=37.5px
手机屏幕大小不同,如何设置不同的HTML标签字号:使用媒体查询检测视口宽度,编写差异化的CSS样式
媒体查询不能定义每个手机尺寸,可以使用flexible.js,这是手机淘宝团队开发的用来适配移动端的js框架,核心原理就是根据不同的视口宽度给网页中html根节点设置不同的font-size值
(4)vw 、vh:也是一个相对单位:
vw:viewport width;1vm=1/100 视口宽度
vh:viewport height;1vh=1/100 视口高度
如设计图为375px;1vm=3.75px;如果盒子大小是75px,那么75/3.75=20vm;width:75px就可以写为width:20vw;
开发中vw和vh不要混用,要么全用vw,要么全用vh,混用可能会导致盒子变形
设备像素比:window.devicePixslRatio
1px问题:CSS样式里的px和物理像素并不是相等的,CSS中的像素只是一个抽象的单位,在不同的设备或不同的环境中,CSS中的1px所代表的物理像素是不同的,在PC端,CSS的1px一般对应着电脑屏幕的1个物理像素,但在移动端,CSS的1px等于几个物理像素
- 伪元素+transform:构建一个伪元素,border为1px,再以transform缩放到50%,
- viewport+rem:通过设置对应的viewport的rem基准值,这种方式就可以像以前一样写1px了
- 设置border-image或者background-image
如何禁用页面中的右键、打印、另存为、复制等功能?
// 禁用右键
document.onmousedown=function(event){
if(event.button===2){
return false
}
}
document.oncontextmenu=function(event){
return false
}
// 禁用复制
<body oncopy="nocopy()">
function nocopy(event){
event.returnValue=false
}
// 禁用f12
document.onkeydown=function(event){
if(window.event && window.event.keyCode===123){
window.event.returnValue=false
}
}
href="javascript:void(0)" 和 href="#"区别是什么?
href="#":锚点默认是#top,会让网页往上走到最上面
javascript:void(0) :阻止事件,是一个固定死链接
对target="_blank" 的理解?有什么安全性问题,如何防范?
打开新的子页面,类似于windoe.open,子页面会拿到当前的句柄(window.opener),就能操作上一个页面的一些信息
if(window.opener){
window.opener.location.href="bad.html"
}
可以修改为
<a .... rel="noopener noreferer">
var otherWindow = window.open('xxx')
otherWindow.opener = null
简述页面测存储区别,什么是本地存储?怎么做离线存储?
(1)cookie:每个cookie不能超过4kb,每个域只能有20个
(2)localStorage:永久存在,大小5M
(3)sessionStorage:会话存储,大小5M
(4)indexDB:离线存储,浏览器数据库
什么是canvas?什么时候需要使用canvas?
画布:浏览器端的绘图工具
常见的动画方案:
css+div:普通网页使用
svg:和传统的html差别不大,html处理矢量绘图能力不足
cavans:比较方便的绘制图形
数据量比较大,动画渲染比较复杂的时候使用cavans
什么是PWA?
渐进式网页应用:一般简单的应用会使用PWA,类似于网页小程序
核心技术:
- app manifest
- service worker(客户端代理)
- web push
什么是Shadow DOM?
shadow dom直译过来就是影子dom,可以理解为DOM中的DOM,因为它能够为Web组件中的DOM和CSS提供封装,实际上是在浏览器渲染文档的时候会给指定的DOM结构插入编写好的DOM元素,但是插入的Shadow DOM会与主文档的DOM保持分离,也就是说Shadow DOM不存在于主DOM树上
Shadow DOM封装出来的DOM元素是独立的,外部的配置不会影响到内部,内部的配置也不会影响到外部
iframe有哪些应用?
- 最常见的一种微前端手段
- ajax上传文件
- 广告
- 解决跨域
如何处理iframe通信?
<body>
<h2>A页面</h2>
<button id="btn">post</button>
<iframe src="http://localhost:8102" id="iframe"></iframe>
</body>
<script>
window.onload = function() {
document.getElementById('btn').addEventListener('click', function() {
var iframe = document.getElementById('iframe');
iframe.contentWindow.postMessage('xxxxx', '*');
})
}
window.addEventListener('message', function(event) {
console.log(event);
})
</script>
<body>
B
<script>
window.addEventListener('message', function(event) {
console.log(event);
event.source.postMessage('i am b ', "*")
})
</script>
</body>
浏览器渲染和布局逻辑是什么?
- 解析时,DOM树的构建
- CSSOM 规则树
- DOM树和CSS规则树,构建成render渲染树
- 页面布局
- 页面绘制
页面的重绘和回流是什么?
回流:又称重排,指改变集合属性的渲染,可以理解为对整个网页填白,对内容重新渲染一次
回流意味着节点的几何属性发生变化,需要重新计算并生成渲染树,导致渲染树的全部或部分发生变化
引起回流的一起场景:
- 页面的初始加载
- 浏览器窗口更改大小
- 元素字体大小变化
- 元素内容发生变化
- js删除或增加元素
- 功能性伪类触发
- 涉及到的一些代码有以下属性或方法:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() 、currentStyle()
重绘:指改变外观属性而不影响几何属性的渲染,相比回流,重绘在两者中会温和一些,回流对浏览器性能的消耗高于重绘
回流一定伴随着重绘,重绘不一定伴随回流
引起重绘的场景:
- color、background 相关属性: background-color、background-image等。
- outline 相关属性: outline-color、 outline-width 、text-decoration
- border-radius、 visibility、 box-shadow
outline是css属性,用于设置元素的外边框样式,包括颜色、样式和宽度。外边框是一个在元素周围的轮廓,类似于边框(border),但不会占用空间,并且不会影响布局
如何避免回流和重绘
(1)CSS:
1、避免使用table布局。
2、尽可能在DOM树的最末端改变class。
3、避免设置多层内联样式。
4、将动画效果应用到position属性为absolute或fixed的元素上。
5、避免使用CSS表达式(例如:calc())。
(2)JavaScript:
1、避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
2、避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
3、也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
4、避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
5、对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
怎么计算首屏和白屏的时间?长统计的页面性能数据指标包括?
window.performance:在埋点的数据分析里,有一项是分析网站性能的,他包含了网站加载时间(含各项事务占比)、dom渲染时间、接口请求响应时间等等。这个涉及到的api就是window.performance
PerformanceObserver:可用于获取性能相关的数据,如,首帧fp、首屏fcp、首次有意义的绘制fmp等
cls监听元素是否回流
页面上有哪些领域可以做进一步的性能优化?
尽量不要引发重绘、回流
- display:none-->visibility:hidden
- 避免使用table布局
- 避免层级过多
- 操作dom insert时,尽量使用fragment,构造完成后一起插入
- 关键动画,使用requestIdelCallback
- 避免首屏加载东西过多
浏览器之间的线程调度是怎样的?
最新的Chrome浏览器包括:1个浏览器主进程,1个GPU进程,1个网络进程,多个渲染进程,和多个插件进程
- 浏览器进程:负责控制浏览器除标签页外的界面,包括地址栏、书签、前进后退按钮等,以及负责与其他进程的协调工作,同时提供存储功能
- GPU进程:负责整个浏览器界面的渲染。Chrome刚开始发布的时候是没有GPU进程的,而使用GPU的初衷是为了实现3D CSS效果,只是后面网页、Chrome的UI界面都用GPU来绘制,这使GPU成为浏览器普遍的需求,最后Chrome在多进程架构上也引入了GPU进程
- 网络进程:负责发起和接受网络请求,以前是作为模块运行在浏览器进程一时在面的,后面才独立出来,成为一个单独的进程
- 插件进程:主要是负责插件的运行,因为插件可能崩溃,所以需要通过插件进程来隔离,以保证插件崩溃也不会对浏览器和页面造成影响
- 渲染进程:负责控制显示tab标签页内的所有内容,核心任务是将HTML、CSS、JS转为用户可以与之交互的网页,排版引擎Blink和JS引擎V8都是运行在该进程中,默认情况下Chrome会为每个Tab标签页创建一个渲染进程
浏览器的渲染进程的线程总共有五种:
(1)GUI渲染线程
负责渲染浏览器页面,解析HTML、CSS,构建DOM树、构建CSSOM树、构建渲染树和绘制页面;当界面需要重绘或由于某种操作引发回流时,该线程就会执行
注意:GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
(2)JS引擎线程
JS引擎线程也称为JS内核,负责处理Javascript脚本程序,解析Javascript脚本,运行代码;JS引擎线程一直等待着任务队列中任务的到来,然后加以处理,一个Tab页中无论什么时候都只有一个JS引擎线程在运行JS程序
注意:GUI渲染线程与JS引擎线程的互斥关系,所以如果JS执行的时间过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞
(3)事件触发线程
时间触发线程属于浏览器而不是JS引擎,用来控制事件循环;当JS引擎执行代码块如setTimeOut时(也可是来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件触发线程中;当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
注意:由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
(4)定时器触发进程
定时器触发进程即setInterval与setTimeout所在线程;浏览器定时计数器并不是由JS引擎计数的,因为JS引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确性;因此使用单独线程来计时并触发定时器,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行,所以定时器中的任务在设定的时间点不一定能够准时执行,定时器只是在指定时间点将任务添加到事件队列中
注意:W3C在HTML标准中规定,定时器的定时时间不能小于4ms,如果是小于4ms,则默认为4ms
(5)异步http请求线程
XMLHttpRequest连接后通过浏览器新开一个线程请求;检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将回调函数放入事件队列中,等待JS引擎空闲后执行
JS事件循环(Event Loop)
JS是单线程,只有一个线程存在,同一时间只能做一件事,这可能会导致JS在处理某些长时间运行的操作(如网络请求、文件系统访问等)时出现阻塞,从而影响用户体验,为了解决单线程运行阻塞问题,JS用到了计算机系统的一种运行机制,即事件循环
在JS中,所有的任务都可以分为:
- 同步任务:立即执行的任务,指的就是前一个任务结束之后再执行后一个任务,程序执行的顺序与任务排序的顺序是一样的,保持同步的,同步任务会直接进入到主线程中执行
- 同步任务在主线程里执行,当浏览器第一遍过滤html文件的时候可以执行完(在当前作用域可以直接执行的所有内容,包括执行的方法、new出来的对象)
- 异步任务:与同步任务是相对的,异步任务不按照任务排序的顺序执行,也可以理解为异步是从主线程中发出一个子线程来完成任务,不进入主线程,直接进入任务队列,只有任务队列通知主线程某个异步任务可以执行的时候,该任务才会进入主线程执行
- 异步任务比较耗费时间与性能,浏览器执行到这些的时候会将其丢到异步任务队列中,不会立即执行
JS中常用的异步任务:setTimeout、setInterval、Promise、Ajax异步请求、DOM事件(click、热size、onload)
同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行,不断重复上述过程就是事件循环
异步任务又可以划分为微任务与宏任务
宏任务是由宿主发起的,而微任务由JavaScript自身发起。
在ES3以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。
微任务:一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前
常见的微任务:
- Promise.then
- MutaionObserver
- Object.observe(已废弃,Proxy对象替代)
- process.nextTick(Nodejs)
宏任务:时间粒度比较大,执行的事件间隔不能精确控制,对一些高实时性的需求不太适合
常见的宏任务:
- srcipt(可以理解为外层同步代码)
- setTimeout、setInterval
- UI rendering、UI事件
- postMessage、MessageChannel
- setImmediate、I/O(Nodejs)
执行一个宏任务,如果遇到微任务,就将它放到微任务的事件队列中,当前宏任务执行完成后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完
async、await:
async是异步的意思,await可以理解为等待,async函数返回一个promise对象,下面这两种方法是等效的
正常情况下,await命令后面是一个Promise对象,返回该对象的结果,如果不是Promise对象,就直接返回对应的值
await会阻塞下面的代码(即加入微任务队列,先执行async外面的同步代码,同步代码执行完,再回到async函数中,执行之前阻塞的代码)
输出结果为:1、fn2、3、2
流程分析:
- 执行整段代码,遇到 console.log(‘script start’) 直接打印结果,输出 script start
- 遇到定时器了,它是宏任务,先放着不执行
- 遇到 async1(),执行 async1 函数,先打印 async1 start,下面遇到await怎么办?先执行 async2,打印 async2,然后阻塞下面代码(即加入微任务列表),跳出去执行同步代码
- 跳到 new Promise 这里,直接执行,打印 promise1,下面遇到 .then(),它是微任务,放到微任务列表等待执行
- 最后一行直接打印 script end,现在同步代码执行完了,开始执行微任务,即 await 下面的代码,打印 async1 end
- 继续执行下一个微任务,即执行 then 的回调,打印 promise2
- 上一个宏任务所有事都做完了,开始下一个宏任务,就是定时器,打印 settimeout
- 最后结果:script start、async1 start、async2、promise1、script end、async1 end、promise2、settimeout