1. HTTP 和 HTTPS
1、http 和 https 的基本概念
http: 是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议。
https:是以安全为目标的 HTTP 通道,即 HTTP 下 加入 SSL 层进行加密。其作用是:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。
2.http 和 https 的区别及优缺点?
- http 是超文本传输协议,信息是明文传输,HTTPS 协议要比 http 协议安全,https 是具有安全性的 ssl 加密传输协议,可防止数据在传输过程中被窃取、改变,确保数据的完整性(当然这种安全性并非绝对的,对于更深入的 Web 安全问题,此处暂且不表)。
- http 协议的默认端口为 80,https 的默认端口为 443。
- http 的连接很简单,是无状态的。https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。
- https 缓存不如 http 高效,会增加数据开销。
- Https 协议需要 ca 证书,费用较高,功能越强大的证书费用越高。
- SSL 证书需要绑定 域名。
3.https 协议的工作原理
客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤:
客户端使用 https url 访问服务器,则要求 web 服务器建立 ssl 链接。
web 服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),传输给客户端。
客户端和 web 服务器端开始协商 SSL 链接的安全等级,也就是加密等级。
客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话密钥,并传送给网站。
web 服务器通过自己的私钥解密出会话密钥。
web 服务器通过会话密钥加密与客户端之间的通信。
2、H5新增标签有哪些?
语义化标签:
header、footer、nav、aside、section、article
语义化的意义?
(1) 让页面的内容结构化,为了在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构。
(2) 用户体验:例如title、alt用于解释名词或解释图片信息、label标签的活用;
(3) 有利于SEO搜索引擎优化:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
(4) 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
(5) 便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
(6)易读、易书写、易理解
3、多媒体标签
视频标签:video
属性:src、 Poster(加载等待画面的图片)、muted(静音)
音频标签: audio
属性:src、loop、controls(调出当前控件)
4、表单元素、控件
输入框input中新增 type,类型可为、email、url、data、number等
required、placeholder
5、src和href的区别
src和href都是对外部资源的引用,区别如下:
src: 表示对资源的引用,用在js脚本、img、frame等元素上,当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到该资源加载、编译、执行完成,所以js脚本会放在页面的底部,而不是头部。
href:表示超文本引用,指向一些网络资源,当浏览器识别它指向的文件时,就会并行下载资源,不会停止对当前文件的处理,用在a、link上。
6、同源策略
1、同源策略是一种浏览器的安全机制,如果出现协议,域名,端口,三者不统一,就会产生跨域
https://www.baidu.com
http://www.baidu.com //协议不同,跨域
http://www.baidu.com
http://mail.baidu.com 二级域名
http://aaa.bbb.baidu.com 三级域名 域名不同,跨域
http://www.baidu.com:8080
http://www.baidu.com:5500 端口不一致,跨域
2、怎么解决跨域(cors)
1)、在后端的响应头加上一句 Access-Control-Allow-Origin:*,这里的*表示所有请求,都可以访问该服务。
2)、采用非官方的跨域方案 ,JSONP, 它算不上真正ajax请求,它只能算get请求,因为它是利用了带src属性的script,不受限制的访问外部资源,再又结合callback回调函数获取数据.
还要和后端配合使用
3)、前端使用webpack模块中的server proxy ,实现服务器端代理,来解决跨域
3、什么是CORS
1、CORS是一个w3c标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器发送XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
2、CORS需要浏览器和服务器同时支持,整个CORS通信过程,都是浏览器自动完成不需要用户参与,浏览器一旦发现跨域请求,就会添加一些附加的头信息。
注:目前所有最新浏览器都支持该功能,但是万恶的IE不能低于10
代码如下:
-
在Vue项目的根目录中找到或创建
vue.config.js
文件。 -
在
vue.config.js
文件中添加代理配置
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://example.com', // 目标服务器地址
changeOrigin: true, // 是否改变源地址
pathRewrite: {
'^/api': '' // 重写路径
}
}
}
}
}
this.$http.get('/api/data').then(response => {
console.log(response.data);
});
这样配置后,所有前缀为/api的请求都会被代理到http://example.com,代理服务器会自动处理CORS问题。请确保目标服务器http://example.com已经配置好了CORS,允许来自你本地开发服务器的请求。
7、JSON和JSONP的区别
json是一种轻量级的数据结构,能跨平台进行网络传输,能做配置文件.
jsonp 是一种非官方的跨域解决方案,它是利用script的src,不受限制的访问外部资源,并结合callback拿到数据
它并不是真正的ajax,它是一个get请求,更加适合做查询.
xml 可扩展性标记语言,是一种重量级的数据格式,也能跨平台进行网络传输和配置文件.
8、new操作符做了什么?
1.在构造函数内部(隐式)创建一个空对象
2.空对象的指针( __ proto __ )指向构造函数的原型(prototype)
3.构造函数的this指向空对象、给空对象添加(自定义的)属性和方法
4.隐式的返回 return this
5、所以new 能改变构造函数内部的this指向,函数内部的this默认是window
function Perosn(name, age) {
// 1.在构造函数内部创建一个空对象
// var obj = new Object();
//2. obj.__proto__= Perosn.prototype;
//3.1 Perosn.bind(obj) this指向obj
//3.2 让空对象拥有 属性和方法 (让this有属性和方法)
this.name = name; //属性
this.age = age; //属性
this.run = function () { }//方法
//4. return this; 是隐式 (看不见的,默认)
// return this;
}
var person = new Perosn("旺旺", 6);
console.log(person);
9、this的理解
1、单独使用 this,它指向全局(Global)window对象。
2、在对象方法中, this 指向调用它所在方法的对象。
3、函数使用中,this 指向函数的所属者。
4、严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。
5、绑定事件this 指向了接收事件的 HTML 元素。apply 和 call 允许切换函数执行的上下文环境(context),即 this 绑定的对象,可以将 this 引用到任何对象。
6、箭头函数中this,沿作用域链向外找,直到有this定义(不受内部定时器影响)
什么是箭头函数
1、没有this,this指向上下文对象
2、不能被实例化
3、没有构造器
4、如果函数体中只有一句代码 且省略了{} 且你需要返回值 那么必须省略return关键词,如果返回的是对象要用括号括起来
箭头函数为什么没有this指向
因js中一开始函数的设计是有缺陷的,因为一个普通函数可以有两种作用域,静态作用域和动态作用域(词法环境)
functon promise() {
this.PromiseStatus = 'pending'
}
let promise = new Promise() //1
promise() //2
普通函数即可以被用来创建实例(1),又可以被调用执行一段指令序列(2),我们看到一个普通函数也不确定这个函数到底是用来来创建实例还是用来执行一段指令,所以箭头函数设计的初衷就是为了解决函数的二义性(创建实例,执行序列),为了解决这一问题,ES6引入了Class和箭头函数的概念,Class只能用过new关键字来创建实例,而普通函数只能执行一段指令序列,故箭头函数设计的初衷就是不应被创建实例的,因此它内部不存在this指向
10、堆和栈的区别是什么
1、内存操作场景
1、栈由操作系统自动分配和释放,用于存放简单的数据段,占据固定大小的空间,比如基本数据类型(Number、String、Boolean……)和函数的参数值等。
2、堆由开发人员自主分配和释放,若不主动释放,程序结束时由浏览器回收,用于存储引用类型(引用类型的变量实际上保存的不是变量本身,而是指向内存空间的指针)。
2、数据结构场景
JavaScript存在栈和队列概念,通过数组的方式,模仿实现堆栈。
栈:栈是一种运算受限的线性表,其限制是指只仅允许在表的一端进行插入和删除操作,这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。把新元素放到栈顶元素的上面,使之成为新的栈顶元素称作进栈、入栈或压栈(Push);把栈顶元素删除,使其相邻的元素成为新的栈顶元素称作出栈或退栈(Pop)。通过数组的push()、pop()方法实现栈。
堆:堆其实是一种优先队列,也就是说队列中存在优先级,比如队列中有很多待执行任务,执行时会根据优先级找优先度最高的先执行。
11、进程与线程的区别
1、线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
2、一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线3、进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
4、调度和切换:线程上下文切换比进程上下文切换要快得多
12、cookie 、sessionStorage与localStorage的区别
特性 | cookie | sessionStorage | localStorage |
数据的生命期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 仅在当前会话下有效,关闭页面或浏览器后被清除 | 除非被清除,否则永久保存 |
存放数据大小 | 4K左右 | 一般为5MB | 一般为5MB |
与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 |
易用性 | 需要程序员自己封装,源生的Cookie接口不友好 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 |
提供方法 | 需自己编写或引用第三方库 | 1).setItem (key, value) —— 保存数据,以键值对的方式储存信息。 | 1).setItem (key, value) —— 保存数据,以键值对的方式储存信息。 |
cookie、localstorage和sessionStorage三者都是临时存储客户端会话信息或数据的方法,下面就简单介绍一下三者的区别:
存储的时间有效期不同
1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
3、localStorage的有效期是在不进行手动删除的情况下是一直有效的
存储的大小不同
1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)
与服务端的通信
1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信
13、前端性能优化
1、defer和async的区别
defer:在HTML解析完之后才会执行。如果是多个,则按照加载的顺序依次执行。
async:在加载完之后立即执行。如果是多个,执行顺序和加载顺序无关
<script src="./async1.js" async defer></script>
2、 减少 HTTP 请求数量
基本原理:在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
CSS Sprites:国内俗称 CSS 精灵,这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数,节省命名词汇量(由命名多张图片文件变成一张,哈哈哈)。
合并 CSS 和 JS 文件:现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
采用 lazyLoad:俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。
3、控制资源文件加载优先级
基本原理:说到这里就需要知道浏览器加载 HTML 内容的原理,浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,解析到 link 或者 script 标签就会加载 href 或者 src 对应链接内容,为了第一时间展示页面给用户,就需要将 CSS 提前加载,不要受 JS 加载影响。
遵循原则:主要文件放在 head 内部,次要文件放在 body 底部。一般情况下都是 CSS 在头部,JS 在底部。
4、利用浏览器缓存
基本原理:浏览器缓存分强缓存和协商缓存,他们是将网络资源存储在本地,等待下次请求该资源时,如果命中就不需要到服务器重新请求该资源,直接在本地读取该资源。
强缓存:在 web 服务器返回的响应中添加 Expires 和 Cache-Control Header。
协商缓存:通过【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对 Header 分别管理。
5、 使用 CDN
基本原理:CDN的全称是Content Delivery Network,即内容分发网络。
减少重排(Reflow)
基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
减少 Reflow,如果需要在 DOM 操作时添加样式,尽量使用 增加 class 属性,而不是通过 style 操作样式。
6、减少 DOM 操作
使用createDocumentFragment
mdn描述:DocumentFragments (en-US) 是 DOM 节点。它们不是主 DOM 树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到 DOM 树。在 DOM 树中,文档片段被其所有的子元素所代替。
语法:let fragment = document.createDocumentFragment();
使用案例
const em = document.createDocumentFragment()
function createBoxes() {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const box = document.createElement('div')
box.classList.add('box')
box.style.backgroundPosition = `${-j * 125}px ${-i * 125}px`
em.appendChild(box)
}
}
boxesContainer.appendChild(em)
}
createBoxes()
7、图标使用 IconFont 替换
14、网络安全
1、什么是xss攻击
如何防范?
1、请求方式:尽量采用POST而非GET提交表单
2、输入验证和过滤:对用户输入进行验证和过滤,确保只允许合法的数据输入。
3、输出转义“在输出用户输入到页面时,使用适当的转义函数将特殊字符转义为 HTML 实体,防止脚本被执行
4、HTTP 头部设置:使用 Content Security Policy(CSP)等 HTTP 头部设置,限制浏览器执行外部脚本的能力。
5、使用安全框架:使用安全框架,例如 Laravel、Django 等,它们通常提供了自动的输入验证和输出转义机制。
6、定期安全审计:定期进行安全审计,检查应用程序中是否存在潜在的 XSS 漏洞,及时修复已知漏洞7、后端需要对提交的数据进行过滤
15、什么是oop(面向对象)
oop(面向对象)是一种编程思想,又叫做面向对象编程(ooa面向对象分析,ood面向对象设计)
它有三大特性封装、继承、多态。
1、这种编程方式,更加贴近现实。
2、java,c#, c++ , js … 面向对象编程,是主流。
封装:将相同的属性和方法提取成一个类
继承:子类拥有父类的属性和方法
多态:重写子类重写父类的属性和方法
重载:在同一个类中,同名不同参数 js没有重载同一个类中,同名不同参数 (在同一个类中,函数名称相同,参数的个数和类型不相同)
注意: js没有重载
3、面向对像继承
1. 对象冒充继承 使用 bind,call,apply 解决构造函数属性的继承
缺点:不能继承原型上的属性和方法
2. 原型链继承
缺点:不能让构造函数的属性,初始化
3. 组合继承 (对象冒充+原型继承)
缺点:原型中会有多余的属性,并且是undefined
4. ES6的class和extends继承
5. 寄生组合继承 Object.create(base.prototype);
4、什么是面向过程?与面向对象有什么区别?
面向过程:
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,
使用的时候一个一个依次调用就可以了。
面向对象:
是把构成问题的事务分解成各个对象,每个对象都有自己独立的属性和行为,
对象可以将整个问题事务进行分工, 不同的对象做不同的事情,
这种面向对象的编程思想由于更加贴近实际生活, 所以被计算机语言广泛应用。
js有2种编程模式:面对过程、面向对象
递归
1、函数自己调用自己,要有零界点(结束条件)
2、循环的能做的事,递归都能实现
递归的使用场景
1. 快速排序使用递归
2. nodejs磁盘文件的遍历,使用递归
3. 管理系统的权限菜单栏(n级菜单栏)
4. 对象的深拷贝
类和对象的关系
类是对象的抽象,而对象是类的具体实例。
类是抽象的,不占用内存,而对象是具体的,占用存储空间。
类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
类与对象的关系就如模具和铸件的关系
类的实例化结果就是对象,而对一类对象的抽象就是类,
类描述了一组有相同属性和相同方法的对象
16、原型
1.什么是原型?
原型就是每个函数都拥有一个protoType属性,该属性指向的对象称为“原型对象”。原型分为“隐式原型”和“显示原型”。
2.原型的作用?
原型的作用是: 可以让同一个构造函数创建的所有对象共享属性和方法. 也就是说, 你可以不在构造函数中定义对象的属性和方法,而是可以直接将这些信息添加到原型对象中。
3.原型的好处?
1, 实例对象都有自己的独有属性
2, 同时共享了原型中的方法,最大限度的节省了内存
3, 支持向构造函数传递参数 (初始值)
4.什么是原型链?
每个对象都拥有一个原型对象,通过_proto_指向其原型对象,并从中继承方法和属性。
当访问一个实例对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找的过程就会形成一个链式结构,我们-称为原型链。
17、Promise
回调函数是用来解决异步或对函数进行功能扩展,如果滥用回调函数的嵌套,就会形成回调地狱
回调地狱,不方便维护与代码的理解,就可以采用Promise.(不仅能解决回调地狱还能做并发)
promsie是一个类,需要被实例化,微任务
promsie 有三种状态
1.pending 等待 默认是 等待
2.fulfilled 完成
3.rejected 拒绝
它们顺序是不可以逆的
promsie的原型方法
then() 里面有2个函数,第1个函数取resolve的结果,第2个参数取reject的结果
catch() 捕获 reject的结果
finally() 只要执行resolve或reject后,都会执行finally
promise的静态方法
Promise.all() ,all方法里需要填入一个数组,数组里必须都是支持promise的方法,迸发执行
Promise.race(),race方法里需要填入一个数组,谁先完成,就只取谁的结果
Promise.resolve() 只执成功,并返回一个新的promise对象
Promise.reject() 只执失败,并返回一个新的promise对象
18、ES7 async await
await关键字后面必须接promise对象,有await关键字的地方,必须是一个async 异步函数
19、什么是闭包(Closure)
闭包是这样一种机制:函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回。
闭包的优点:
- 避免全局变量的污染
- 能够读取函数内部的变量
- 可以在内存中维护一个变量
闭包的缺点:
- 闭包会常驻内存,会增大内存使用量,导致一定程度上的内存泄露。
- 在游览器中因为回收机制无法回收闭包的函数以及闭包函数中储存的数据,会使游览器占用更多的性能开销
闭包的用途
1.实现缓存
2.存储值与避免变量全局污染
3.函数的柯里化
4.节流和防抖
- 延伸了函数的作用范围,读取函数内部的变量
- 让变量的值始终保持在内存中。不会在调用后被自动清除。
- 方便调用上下文的局部变量。利于代码封装。
使用闭包的注意点
1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
2、闭包会在父函数外部,改变父函数内部变量的值。
示例代码如下:
- 普通的闭包
// JS中的一个函数如果访问了外层的一个变量就会形成闭包
var sge=12;
function add(){
console.log(sge);//访问函数外部的变量就形成闭包
}
add()
- 严格闭包
function f(){
var name="zhangsan";
function s(){
console.log("abb",name);
}
return s;
}
var ff=f();
ff();
闭包的内存泄露
闭包的内存泄漏主要是指 :
- 在形成闭包时 : 包含了一个父级作用域 f(); 有内存指向他 还存在AO 因此不会被销毁;
- 在程序不断执行时 因为需要不断调用这个函数就会造成内存泄漏
- 内存泄漏主要是看你需不需不断使用
- 不使用了还存在就是内存泄漏
那么,怎么解决这个问题呢?
-
因为当将add10设置为null时,就不再对函数对象0xb00有引用,那么对应的AO对象0x200也就不可达了;
-
在GC的下一次检测中,它们就会被销毁掉;
function f(){
var name="zhangsan";
var age=18;
function s(){ //指针?
console.log(name,age);
} //这里的s函数对象是指向f() 在函数执行完毕后A0不会被销毁 保存了下来
return s;
}
var obj=f();
obj();
obj=null // 指向空销毁内存空间
20、JavaScript的事件循环机制
JavaScript语言最大的特点就是单线程,即同一时间只能做一件事情,做完一件事情之后才能去做另一件事情。单线程就意味着所有任务需要排队,前一个任务结束才会执行后一个任务。
同步任务(synchronous):
同步任务指的是:在主线程上排队执行的任务,只有前一个任务执行完毕才能执行后一个任务。所有的同步任务都在主线程上执行,形成了一个执行栈。执行栈的执行顺序是后进先出。
异步任务(asynchronous):
异步任务指的是:不进入主线程,而是进入“任务队列”的任务。只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行
事件循环过程:
同步任务和异步任务分别进行不同的场所,同步任务进入主线程,异步任务进入事件表(Event Table)并且注册函数。当指定的事情完成之后(例如接受到了Promise对象的返回结果resolve/reject),事件表(Event Table)会将这个函数移入到任务队列(Event Queue)。主线程内的任务执行完毕之后,回去任务队列(Event Queue)读取对应的函数,移入到主线程执行。上述过程不断重复,这就是事件循环(Event Loop
宏任务和微任务
宏任务(macro-task)包含:整体代码script、setTimeout函数、setInterval函数。
微任务(micro-task)包含:Promise、process.nextTick。
事件循环的顺序决定了JavaScript代码的执行顺序。首先进入整体代码script对应的脚本文件之后,开始第一次的循环。
接着执行所有的微任务,然后再次从宏任务开始执行,找到对应的任务队列执行完毕,再次执行所有的微任务,以此循环。
在执行宏任务或者微任务的过程中,里面的微任务的优先级是大于宏任务的,也就是先执行微任务再执行宏任务。
案例如下:
分析一下代码段的执行过程,并写出输出结果:
setTimeout(()=>{
console.log("定时器")
})
new Promise(funtion(resolve,reject){
console.log("Promise")
resolve()
}).then(res=>{
console.log("回调")
})
console.log("结束")
标签:浏览器,函数,对象,前端,http,面试,任务,八股文,执行 From: https://blog.csdn.net/m0_49008668/article/details/141874852任务执行过程
1、首先进入整个js文件,是一个宏任务。2、遇到setTimeout宏任务,这是一个异步任务,进入事件表(Event Table)并注册函数,等定时结束之后将函数移入到任务队列(Event Queue)
3、遇到 new Promise执行同步代码console.log("Promise"),输出Promise。接收到resolve的返回结果,遇到then回调微任务,进入事件表(Event Table)并注册函数,然后将这个函数移入到任务队列(Event Queue)
4、遇到console.log("结束")。输出结束
5、一轮宏任务处理完毕,判断是否有微任务需要处理。有then回调微任务,输出Promise回调
6、一轮事件循环结束,先找到setTimeout宏任务执行,输出定时器,再继续寻找是否有微任务?没有,开始下一轮事件循环。是否有宏任务可以进行循环?没有,事件循环结束。