H5题目
1. 如何理解HTML5结构语义化
a) 用正确的标签做正确的事情,
b) 对于开发者:便于团队的开发和维护;在没有加载css的情况下也能呈现较好的内容结构,易于阅读
c) 对于浏览器:有利于SEO,搜索引擎的爬虫依赖于标签来确定上下文和关键字的权重;方便其他设备的解析(如屏幕阅读器,盲人阅读器等),利于无障碍阅读,提高可访问性。
2. H5的新特性
a) 主要是关于多媒体,位置,存储,多任务等功能的增加
i. 用video,audio元素播放音视频
ii. 本地离线存储localStorage长期存储数据,浏览器关闭后数据不会丢失
iii. sessionStore数据在浏览器关闭后自动删除
iv. 语义化更好的标签:article、footer、header、nav、section
v. 表单控件:calendar、date、time、email、url
vi. 新的技术:webworker(起一个新的线程)、websocket(即时通讯)、geolocation(获取地理位置信息)
b) 移除的元素
i. 纯样式元素:big、center、s、u、
ii. 产生负面影响的元素:frame、frameset、noframes
3. 描述cookie、sessionStorage、localStorage的区别
a) Cookie是网站为了标识用户身份而储存在用户本地终端上的数据(通常经过加密)
b) Cookie数据始终在同源的http请求中携带(即使不需要),即会在浏览器和服务器间来回传递;sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存
c) 存储大小
i. Cookie数据大小不能超过4k
ii. sessionStorage和localStorage也有大小限制,但比cookie大得多,可以达到5M或更大
d) 过期时间
i. Cookie设置的过期时间,在过期时间之前一直有效,即使窗口或浏览器关闭
ii. sessionStorage数据在当前浏览器窗口关闭后自动删除
iii. localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除
4. 浏览器的渲染机制
a) 处理HTML并构建DOM树
b) 处理CSS构建CSSDOM树
c) 将DOM与CSSOM合并成一个渲染树
d) 根据渲染树来布局,计算每个节点的位置
e) 调用GPU绘制,合成图层,显示在屏幕上
f) 注意:
i. 在构建CSSOM树时会阻塞渲染,直至CSSOM树构建完成,构建CSSOM树十分消耗性能,应尽量减少标签和类名的过度层叠,越是具体的CSS选择器,执行速度越慢(css解析的时候从右向左开始解析)
ii. 在解析script标签时,会暂停构建DOM,加载完成后才会从暂停的地方重新开始,应尽量减少首屏js文件的加载。
5. 重绘(repaint)和回流(reflow)
a) 重绘是是指网页渲染引擎根据显示属性 (如颜色、文字大小等) 重新绘制页面元素,不影响元素的位置和尺寸;
b) 回流是指网页渲染引擎根据元素的尺寸、位置和显示属性来重新计算页面的排版和布局
c) 回流必然发生重绘,重绘不一定回流
d) 影响性能的动作
i. 添加或删除可见的DOM元素
ii. 元素的位置发生变化
iii. 元素的尺寸发生变化(padding,margin,border,width,height)
iv. 内容发生变化(如:文本变化,图片变化)
v. 定位或浮动
vi. 浏览器窗口尺寸的变化(回流是根据视口的大小来计算元素的位置和大小)
e) 减少重绘和回流
i. 批量修改DOM
ii. 对于复杂动画效果使用绝对定位让其脱离文档流
iii. Css3硬件加速(GPU加速)transform、opacity、filters这些动画不会引起回流重绘
6. 简述data属性的用法(如何设置,如何获取),有何优势
a) data-*的值的获取和设置
i. 传统方法,getAttribute()获取data-属性值;setAttribute()设置
ii. H5新方法:eg: data-name;
1. e.target.dataset.name // 获取值
2. e.target.dataset.name = ‘aa’ // 设置值
CSS题目
1. display:none; 与visibility: hidden;的区别
a) 都可以让元素不可见
b) 区别
i. display:none; 会让元素从渲染树中消失,渲染的时候不占据任何空间;visibility:hidden;不会让元素从渲染树消失,元素继续占据空间,只是内容不可见。
ii. 修改文档流中元素的display会造成文档重排,修改visibility属性只会造成元素的重绘
2. Margin塌陷与margin合并
a) 在文档流中父子元素或相邻的两个或者多个元素垂直方向上的margin会折叠
b) 创建了块级格式化上下文(BFC)的元素,不会发生margin塌陷
c) 如何触发BFC/解决margin塌陷问题
i. 设置float:left/right
ii. 设置overflow:hidde/scroll/auto
iii. 设置position:absolute/fixed
iv. 设置display:inline-block/table-cell/table-caption
v. 那一个对样式没有影响就用那个
3. z-index是什么?什么时候可以触发?
a) z-index属性可以设置元素的堆叠顺序
b) 仅在元素设置了position: absolute/fixed/relative时有效(position的值不为static)
c) 判断堆叠顺序不仅仅是直接比较两个元素的z-index值,堆叠顺序由元素的层叠上下文、层叠等级共同决定
i. 一个元素有了层叠上下文,就离屏幕观察者更近了
1. 为“根层叠上下文”
ii. 层叠等级:
1. 在同一个层叠上下文中,他描述定义的是该层叠上下文中的层叠上下文元素在z轴上的上下顺序
2. 在其他普通元素中,它指的是,这些元素在z轴上的上下顺序
iii. 不在同一层叠上下文中的层叠等级比较没有意义
iv. 层叠顺序
1. 表示元素发生层叠时,按照特定的顺序规则在z轴上垂直显示
a) 层叠上下文(background/border) -> z-index<0 -> block块级元素 -> float浮动元素 -> inline/inline-block水平盒子 -> z-index: auto/z-index: 0 -> z-index > 0
i. 层叠上下文(background/border) 指的是层叠上下文元素的背景和边框
ii. Inline/inline-block元素的层叠顺序要高于block/float (发生层叠时优先显示文字内容)
2. Css3中属性对层叠上下文的影响
a) 父元素的display属性为flex/inline-flex,子元素z-index属性值不为auto的时候,子元素为层叠上下文元素
b) opacity属性值不为2
c) transform属性值不为none
d) filter属性不为noene
e) isolation属性值为isolate
4. 简述box-sizing的值以及所对应的盒模型规则
a) box-sizing:content-box | border-box | inherit
i. content-box: width = content
ii. Border-box: width = content + padding + border
5. 移动端适配怎么做
a) viewport
i. 通过设置viewport设置页面大小,通过meta标签可以设置viewport信息
ii. viewport属性
1. width: 视口宽度,正整数或设备宽度device-width(width = device-width)
2. height:视口高度,正整数或设备高度device-height
3. initical-scale:网页初始缩放值,小数缩小,反之放大(initical-scale = 1.0)
4. maximum-scale:设置页面的最大缩放比例(maximum-scale = 1.0)
5. minimum-scale:设置页面的最小缩放比例(minimum-scale = 1.0)
6. user-scaleble:用户是否可以缩放(user-scaleble = no)
iii. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
b) 两套页面
i. 通过配置两套不同路由判断是否是移动端
ii. router.addRoute(isMobile() ? mobileRoutes[1] : pcRoutes[1])
c) 搭配工程化postcss-pxtorem/amfe-flexible(px,em,rem)
i. amfe-flexible 配置可伸缩布局方案,主要是将1rem设为viewWidth/10
ii. postcss-pxtorem:将像素单位转为rem(相对于根元素的font-size)
iii. 如何使用
1. 安装amfe-flexible和postcss-pxtore
npm install amfe-flexible --save
npm install postcss-pxtorem --save
2. 在main.js中引入
import ‘amfe-flexible' // main.js
3. 配置postcss-pxtorem
a) 可在vue.config.js/.postcssrc.js/postcss.config.js其中之一配置,权重从左到右降低,没有则新建文件,只需要设置一个即可
b) 在 vue.config.js 配置
c) 在.postcssrc.js/postcss.config.js配置(上图二)
d) rootValue根据 设计稿宽度/10 进行设置,这边假设设计稿为375
i. document.documentElement.style.fontSize = document.documentELement.clientWidth / 设计稿宽度 * 100 + ‘px’
e) propList是设置需要转换的属性,这边*为所有都进行转换
d) 图片适配
{max-width:100%} 此时图片会自动缩放,且不会被拉伸变形
e) 媒体查询
根据不同的分辨率设置不同的样式: @media screen and(min-width: 1200px) {}
6. 什么是CSS3 transform?transition?animation?
a) transform:描述了元素的静态样式,本身不会呈现动画效果,可以对元素进行旋转rotate、扭曲skew、缩放scale和移动translate以及矩形变形matrix
i. div { transform: scale(2) }
ii. transform常常配合transition和animate使用
b) transition:样式过渡,从一个效果逐渐过渡到另一个效果
i. transition是一个简写属性:transition-property transition-duration transition-timing-function transition-delay(CSS属性 过渡时间 速度曲线 延迟变换时间)
ii. div { width: 100px; height: 100px; transition: transform 2s} // 检测transform属性
div: hover { transform: rotate(180deg) }
iii. transition通常和hover等事件配合使用,需要由事件来触发过渡
iv. 一些限制
1. 需要事件触发,如:hover,不能自动发生
2. 一次性的,不能重复发生,除非一再触发
3. 只有两个状态开始和结束,不能定义中间状态
4. 只能定义一个属性的变化,不能涉及多个属性
c) animation:由@keyframes来描述每一帧的样式
i. div { animation:myAnimation 5s infinite }
@keyframes myAnimation {
0% {left:0, transform: rotate(0);}
100% {left: 200px; transform: rotate(180deg)}
}
d) 区别:
i. transform描述元素的静态样式, 常常配合transition和animate使用
ii. transition通常和hover等事件配合使用,需要由事件来触发过渡
iii. animation可设置循环次数
iv. animation可以描述每一帧的样式和时间,transition只能设置开始和结束
v. transition可以和js配合使用,js设置变化的样式,transition负责动画
7. 父元素和子元素宽高不固定,如何实现水平垂直居中
a) 父元素设置:position:relative;
子元素设置:position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)
b) 父元素设置:display: flex; justify-content: center; align-items: center;
c) 父元素设置:display: flex;
子元素设置:margin: auto
8. 假设高度默认100px,请写出三栏布局,其中左栏右栏各为300px,中间自适应
a) 浮动
b) 绝对定位
i. 父元素:position:relative;
ii. 子元素:.left { width: 300px; position: absolute; left: 0; } .right { width: 300px; position: absolute; right: 0; } .center { width: 300px; position: absolute; left: 300; right: 300px }
c) flex布局: flex: 1
JS题
1. Js有哪些内置对象
a) 数据封装类对象: Object、Array、Boolean、Number、String
b) 其他对象:Function、Arguments、Math、Date、RegExp、Error
c) ES6新增对象:Symbol、Map、Set、Promises、Proxy、Reflect
2. JS原型链
a) 原型分为函数原型prototype(显示原型)和对象原型__proto__(隐式原型)
i. 对象只有__proto__, 函数既有prototype也有__proto__, 函数也是对象。
ii. Prototype:每个函数都有一个特殊的属性称为prototype,是函数被创建时自动生成的一个对象,函数对象用于存储可以被函数的所有实例共享的属性和方法
function Person(name) { this.name = name };
Person.prototype.sayHello = function () { console.log(this.name) }
iii. 实例对象可以修改显示继承的属性和方法(如:name),但无法修改原型上的属性和方法(如:sayHello)
1. 当原型对象的属性为基本类型的数据值时,实例对象无法修改原型上的属性值,person1.age = 1; 此时是给实例person1增加了一个属性age并赋值为1,并未修改原型的age值
2. 当原型对象的属性值为引用类型的数据时,实例对象可能会修改原型上的属性。person1.age = [1, 2], person2.push(2),person1的行为同上,person2则会修改原型上的age值。
iv. proto:每个对象都有一个特殊的内部属性,它指向该对象的原型,可以是另一个对象或者null。
person1 = new Person(‘Alice’) console.log(person1.proto) // Peroson.prototype
v. 关系:
1. 通过函数原型,可以创建实例对象的共享方法和属性。
2. 当你创建新的实例时,JS引擎会自动将对象的__proto__设置为构造函数的prototype
3. 实例的constructor指向构造函数,即person1.constructor === Person // true
4. Person.prototype.construction === Person // true
b) 原型链
i. 原型链是js用于实现继承和属性查找的一种机制。当我们从object中读取一个缺失的属性时,JavaScript会自动沿着原型链查找,直到找到相应的属性或到达原型链的顶端(Object.prototype: null)为止,如果找不到相应的属性或方法,则返回 undefined。
ii. 继承:
1. function Animal(name) {this.name = name} ;
Animal.prototype.sleep = function() { console.log(‘sleeping’) }
function Dog (name) { Animal.call(this, name) };
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog;
2. let animal = {eats: true}; let dog = {proto: animal, jump: true}
3. 跨域和同源策略
a) 同源策略是浏览器的一种机制,只允许在同协议、同域名、同端口号的情况下才能进行数据交互,否则就会发生跨域
b) 解决跨域的方法
i. CORS技术: 服务端设置一个允许跨域响应头即可:res.setHeader(‘Access-Control-Allow-Origin’, true)
ii. jsonp: 利用script标签src属性来发送请求,因为跨域只对ajax有限制
const getBook = res => { document.querySelector('#jsonp').remove() }
document.querySelector('button').addEventListener('click', function () {
const script = document.createElement('script')
script.src = 'http://127.0.0.1:3000/aaa?callback=getBook'
script.id = 'jsonp'
document.body.appendChild(script) // 一般动态jsonp会添加到head标签
})
iii. nginx代理:前端->后端会被同源策略限制,后端->后端则不会被限制
通过Nginx代理,先访问已设置CORS的Nginx代理服务器,再让Nginx代理服务器去访问业务服务器,再获取到数据Nginx代理服务器->前端
1. 主要针对服务端不适合直接设置CORS跨域的情况,需要用中间服务进行API跨域的处理
iv. Node代理
1. 跟Nginx一样,都是把请求发给一个中间服务,只是这里我们利用Node自己搭建了一个代理服务器。
v. 框架配置proxy代理、websocket没有同源策略、iframe搭配document.domain/lacation.hash/window.name三种方式实现跨域
4. 闭包
当a函数中返回了b函数,b函数中又使用了a函数中的局部变量(包含参数)就会形成闭包
理论上说a函数执行完成后,生成的b函数应该被垃圾回收机制回收,但是b函数还在使用a函数中的局部变量,就会导致a函数没有及时回收,导致内存泄露。
a) function bar() { console.log(a) } function foo() { var a = 100; bar() }
var a = 200; foo() // 200
bar和foo函数在预编译阶段生成了作用域,并且都生成了一个指向其外层作用域引用outer属性
bar和foo都是声明在外部的,所以他们的outer指向斗志整个外层作用域。当bar输出a但它内部没有时,就是去outer指向的作用域中寻找。
b) 闭包的作用
i. 实现共有变量:在模块化开发中,闭包可以用来创建私有变量并暴露有限的公共接口,实现数据的封装和隔离
ii. 做缓存:利用闭包可以存储计算结果,避免重复计算,提高程序效率
iii. 封装模块,防止全局变量的污染:通过闭包封装变量和函数,可以有效减少全局作用域的污染,保持代码的整洁和可维护性。
c) 闭包缺点:由于闭包对外部变量的引用,可能会导致这些变量及相关的整个作用域链长时间在内存中,从而引发内存泄露,尤其是在大量使用闭包或者循环中创建闭包的情况下,必须谨慎处理,确保不在使用的变量能够及时释放,避免不必要的内存占用。
5. 防抖与节流(闭包的应用)
a) 防抖:当持续触发事件时,一定时间段内没有再触发事件,函数才会执行一次,如果在这个时间段内又触发了事件,则会重新开始延时。常用于输入框搜索、滚动加载等场景。
b) 节流:当持续触发事件时,保证一定时间段内只触发一次事件处理函数。常用于滚动加载、监听窗口大小改变等场景。
6. 数组去重
a) 利用Set() + Array.from()
i. Set对象:是值的集合,你可以按照插入的顺序迭代它的元素,set中的元素只会出现一次,及set中的元素是唯一的
ii. Array.from():对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例
iii. const result = Array.from(new Set ( arr ) )
iv. 该方法对NaN和undefined也是有效的,因为NaN和undefined都可以被存储在Set中,NaN被视为相同的值(尽管在js中NaN !== NaN)
b) 两层循环 + splice方法
i. 通过两层循环对数组元素逐一比较,然后通过splice删除重复元素,不能去重NaN,NaN !== NaN
ii. function removeDuplicate( arr ) {
let len = arr.length
for ( let i = 0; i < len; i++) {
for( let j = 0; j < i + 1; j++) {
if ( arr[i] === arr[j] ) { arr.splice(j, 1); len--; j-- }
}
}
return arr
}
c) 利用数组indexOf方法
i. 新建一个空数组,遍历需要去重的数组,将元素存入新的数组中,存放前判断数组中是否已经含有该元素,若没有则存入,此方法也无法去重NaN
ii. Function removeDouplicate( arr ) {
const newArr = []
arr.forEach(item => { if ( newArr.indexOf(item) === -1 ) { newArr.push(item) } })
return newArr }
d) 利用includes方法
i. 与indexOf方法类似,用includes方法判断是否包含值,if (!arr.includes(item))
ii. 此方法可以去重NaN,(includes方法可以检测)
e) 利用filter() + indexOf()
i. filter方法会对满足条件的元素放到一个新的数组中,结合indexOf方法进行判断
ii. Function removeDuplicate( arr ) {
return arr.filter( ( item, index ) => {
return arr.indexOf(item) === index
} )
}
iii. 此方法会将NaN删除,因为indexOf无法判断NaN,即arr.indexOf(‘NaN’) = -1
f) 利用Map()
i. Map对象是js提供的一种新的数据结构,结构为键值对形式,将数组元素作为map的键存入,然后结合has()和set()方法判断键是否重复
ii. Function removeDuplicate( arr ) {
const map = new Map(); const newArr = []
arr.forEach( item => { if ( !map.has( item ) ) {
map.set(item, true); newArr.push(item) } ;})
return newArr
}
iii. 可对NaN去重
7. 数组合并的方法
a) concat;[...a, ...b];
b) [a.,b].flat():flat(depth)方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合为一个新的数组返回,depth默认为1,扁平化处理数
8. 前端攻击
a) CSRF:跨站请求伪造
i. 用户User浏览并登录信任网站A;验证通过,User处产生A的cookie;用户在没有登出A网站的情况下,访问危险B网站;B要求User访问A网站,发出一个请求(由于A网站的漏洞); User根据B的要求,带着Cookie访问A;A会处理User发过来的请求,这样B就达到了模拟用户操作的目的。
ii. 防范措施:CSRF通常发生在第三方域名;CSRF攻击者不能获取到Cookie信息,只能使用,针对以上两点定制防护措施。
1. 阻止不明外域的访问:
a) 同源检测:在http协议中每个请求header有origin 和referer ,服务器可以通过解析这两个的域名,确定请求的来源域。referer指的是页面请求来源
2. Token验证:要求所有用户携带一个攻击者无法获取的token,服务器校验token来判断请求是否由用户自己发出。
b) XSS攻击:通过一些合法的操作,比如在url中,评论框等输入框中,想你的页面注入脚本(可能是js,html代码块等),导致cookie盗用;破坏页面的正常结构,插入广告等恶意内容;D-doss攻击。
i. 防范:对用户输入的数据进行校验;将用户输入的内容进行转译。
c) CSRF是利用网站本身的漏洞,去请求网站接口,不能获取用户cookie;XSS是向网站注入脚本,执行脚本篡改网站内容。
9. http状态码
a) 1xx: 表示临时响应并需要请求者继续操作。100 继续请求
b) 2xx:成功,操作被成功接收并处理。200 请求成功
c) 3xx: 重定向,301 请求网页已永久移动到新位置304 文件未发生变化(协商缓存)
d) 4xx: 服务器错误,400 服务器不理解请求;401: 未授权,要求身份验证;403 服务器拒绝请求;404: 未找到,服务器找不到请求的网页;
e) 5xx:服务器在处理请求时发生内部错误,时服务器本身的错误,而不是请求出错。
10. 一个页面从输入URL到页面加载显示完成,这个过程发生了什么
a) 解析url:浏览器查找域名对应的IP地址(DNS查询:浏览器缓存 -> 系统缓存 -> 路由器缓存 ->DNS缓存 -> 根域名服务器)
b) 建立tcp连接:得到IP地址后,会通过TCP协议与服务器建立连接,这一过程会进行三次握手,确保双方都已准备好进行通信。(如果是https还需要有加密和证书验证等步骤)
c) 服务器301重定向:输入的url可能时顶级域名,返回二级域名(从baidu.com 重定向到 www.baidu.com)
d) 浏览器跟踪重定向地址,请求另一个网址
e) 发送http请求:请求包含请求行(请求方法、请求url、http版本等),请求头,请求正文
f) 服务器处理请求:
g) 发送http响应:响应包含:状态行(http版本、状态码、状态描述等)、响应头以及响应正文
h) 浏览器解析和渲染页面:浏览器收到响应后,会解析响应正文中的代码,并下载所需的css,js等资源文件,然后浏览器下、根据这些资源渲染页面,将页面呈现给用户。】
11. 进程和线程
进程是资源分配的最小单元,线程是代码执行的最小单元。一个应用程序可能会开启多个进程,进程之间数据不共享,一个进程内部可以开启多个线程,线程之间的数据可以共享,所以在多线程的情况下,需要考虑线程执行顺序问题。
浏览器其实也是通过webWorkers开启多线程。
12. 浏览器缓存:协商缓存和强缓存(减少对服务器的请求次数)
协商缓存和强缓存都是浏览器对静态资源文件(.css, .js, .jpg...)的缓存机制,描述的就是什么时候去服务器请求,什么时候直接读取缓存中的文件。
a) 强缓存是客户端直接查看本地的缓存文件是否过期,没有过期直接取用。
i. 查看过期的方法主要是以来响应头上的expires(绝对时间)和cache-control:max-age:10000s(相对时间, 优先级更高)
b) 协商缓存是客户端去询问服务器对应的文件是否有更新,如果有更新才会重新请求
i. 依靠的是响应头上的last-modified(最后更新时间-服务端)/If-Modified-Since(客户端)及Etag(内容变更的标识-服务端)/If-No-Match(客户端)来确认文件是否有更新,etag优先级更高。未更新返回304, 更新了返回200及新的文件
c) 一个文件是否重新请求要经过强缓存和协商缓存的完整过程后才能决定,资源未过期触发强制缓存,资源过期了出发协商缓存。
d) 如果想要更新资源,可以在静态资源后面添加一个时间戳(.js?t=123423),此时url地址不一样,就会去获取新的数据,阻止浏览器缓存。
13. http和https有什么区别
a) http是明文传输,数据没有加密,安全性较差;https(http + SSL),数据传输过程是加密的,安全性要好一些。
b) https需要到CA(数字证书认证机构)申请证书,一般免费证书较少,需要一定费用。
c) http要比https快一些,http和服务器建立连接通过tcp的三次握手,客户端和服务端只需要交换3个包;https在连接的时候除了tcp的3个包,还有SSL的9个包,一个共12个包。
d) 默认端口不同,http默认80端口,https默认443
e) http过程
i. 地址解析,DNS解析域名得到主机的IP地址
ii. 封装http请求数据包。
iii. 封装成tcp包,建立tcp连接(三次握手)
iv. 建立连接后,客户端向服务器发送一个请求
v. 服务器接到请求后,给与响应信息
vi. 服务器关闭tcp连接
vii. 客户端解析报文,解析html,渲染
f) https过程
首先建立SSL连接,客户端将ssl版本号和加密组件发送到服务器端,服务器端收到后对ssl版本号和加密组件进行匹配,同时将CA证书及密钥发送到客户端。客户端对证书进行验证,验证通过后使用非对称加密对数据通信时的密钥进行协商。协商后得到一致的对称加密密钥,然后使用对称加密算法进行tcp连接,后续与http一致,三次握手,数据交换,四次挥手,通信结束。
14. 事件循环
a) 所有的同步任务在主线程中按顺序执行,形成一个执行栈
b) 主线程之外,还有一个“任务队列”。异步任务(setInterval,setImeout,i/o)有了结果,就在“任务队列”中放置一个事件。
c) 一旦执行栈中的同步任务都完成,系统就会读取“任务队列”,将任务队列中的第一个任务放到执行栈中开始执行。
d) 主线程不断重复上面的过程(c),主线程从“任务队列”中读取事件,这个过程是循环不断地,所以整个运行机制称为事件循环(event loop)
15. 微任务与宏任务
a) 宏任务:
i. 异步宏任务:setTimeout,setInterval,事件监听的回调,ui渲染,I/O(文件,数据库的读写),setImmediate(Node.js)
ii. 同步宏任务:所有script代码
b) 微任务:promise的then、catch、finally(创建promise是同步的), await(async中同步),Generator,MutationObserver, process.nextTick(node.js)
c) 在执行异步时,先执行1个宏任务,然后执行微任务至清空微任务队列,再去执行下一个宏任务。
ES6-ES13高频面试题
1. ES6新增的方法
a) let和const、解构赋值、模板字符串、箭头函数
b) Symbol、Map、Set数据类型
c) Proxy重新定义了数据劫持的能力
d) Reflect定义了一套标准化的数据操作的方法
e) Promise解决回调地狱的问题
2. var、let、const的区别
a) ES6新增了let和const,用于定义块级变量和常量,外部无法使用内部的let和const定义的变量,存在块级作用域限制。var没有块级作用域限制,不存在展示性死区。
let a = 1; if ( true ) { console.log(a); let a = 2 } // 此时会报错;块级作用域存在暂时性死区,只会在该块级作用域内查找变量,不会跳出块级作用域查找。
b) let 不允许重复声明变量
c) Const 是声明常量,定义时必须初始化数据,并且以后都不能修改,否则会报错
d) var会变量提升,可以在定义前使用,let、const不行
3. 箭头函数与普通函数的区别
a) 箭头函数无this,指向window,箭头函数的this无法使用call,apply,bind改变;普通函数指向函数运行时所在的对象。
b) 箭头函数没有原型prototype,没法让他的示例的__proto__属性指向,所以箭头函数无法作为构造函数,用new调用会报错。
c) 箭头函数处于全局作用域中,没有arguments。
i. 当箭头函数处于普通函数作用域中,arguments则是上层普通函数的arguments。
ii. 可以使用rest参数替代,es6 rest用于获取函数不定数量的参数数组,这个API是用来替代arguments的,形式为...变量名,rest参数搭配的变量是一个数组,该变量见多余的参数放入数组中。
func(a, ...arr) { console.log(a, arr) }; func(1,2,3,4,5) // 1,[2,3,4,5]