前端基本面试概况

​1、网页从输入网址到渲染完成经历了哪些过程?
    大致可以分为如下7步:
    1、输入网址;
    2、查看本地是否有缓存,如果没有缓存的话,发送到DNS服务器,并获取域名对应的web服务器对应的ip地址;
    3、与web服务器建立TCP连接;
    4、浏览器向web服务器发送http请求;
    5、 web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址);
    6、 浏览器下载web服务器返回的数据及解析html源文件;
    7、生成DOM树,解析css和js,渲染页面,直至显示完成;


2、URL 的组成
    1、协议(HTTP):规定数据传输的方式
    2、域名(IP):在网络环境中找到主机-------用 :// 与协议分隔开
    3、端口(port):(常省略)在网络主机上,标识一个进程(应用程序)------用  :  与域名分隔开
    4、资源路径:标识网络资源(文件,图片,音视频,变量...)------用 :// 与端口分隔开
    5、查询参数:传递给资源路径对应的数据------用  ?  与资源路径分隔开,查询内部参数用  &  分隔多个键值对
    6、锚:从“#”开始到最后,都是锚部分。


3、常见的 http 状态码
    1、状态码200:状态码200表示服务器响应成功,也就是服务器找到了客户端请求的内容,并且将内容返回给客户端。
    2、状态码302:状态码302代表临时跳转。例如:URL地址A可以向URL地址B上跳转,但这并不是永久性的,在经过一段时间后,URL地址A还可能向URL地址C上跳转。
    3、状态码301 :状态码301和状态码302相似,不同的是状态码301往往代表的是永久性的重定向,值得注意的是,这种重定向跳转,从严格意义来讲不是服务器跳转,而是客户端跳转的。这个“跳”的动作是服务器是通过回传状态码301来下达给客户端的,让客户端完成跳转。
    4、状态码304:服务器通过返回状态码304可以告诉客户端请求资源成功,但是这个资源不是由服务器提供返回给客户端的,而是客户端本地浏览器缓存中就有的这个资源,因为可以从缓存中获取这个资源,从而节省传输的开销。
    5、状态码403:状态码403代表请求的服务器资源权限不够,也就是说,没有权限去访问服务器的资源,或者请求的IP地址被封掉了。
    6、状态码404:状态码404代表服务器上没有该资源,或者说服务器找不到客户端请求的资源,是最常见的请求错误码。
    7、状态码500:状态码500代表程序错误,也就是说请求的网页程序本身报错了。在服务器端的网页程序出错。由于现在的浏览器都会对状态码500做一定的处理,所以在一般情况下会返回一个定制的错误页面。
    8、 状态码501(尚未实施) 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。
    9、状态码502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
    10、状态码503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。
    11、状态码504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 
    12、状态码505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

4、长连接,短连接、WebSocket
   https://blog.csdn.net/lucylala007/article/details/119351757

5、简单讲解一下http2的多路复用
    在 HTTP/1 中,每次请求都会建立一次HTTP连接,也就是我们常说的3次握手4次挥手,这个过程在一次请求过程中占用了相当长的时间,即使开启了 Keep-Alive ,解决了多次连接的问题,但是依然有两个效率上的问题:
        第一个:串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
        第二个:连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。
    HTTP/2的多路复用就是为了解决上述的两个性能问题。在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
    多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

6、https请求过程和加密过程,以及http和https的区别
    请求过程:

    client发起建立tcp连接:三次握手;
    client say-hello:client发送hello包给server,报文包含时间戳和随机数、会话ID(session_id)、密文族(即client支持的加密方法名称列表)等;
    server say-hello:server接收到client的hello包后进行一些处理,如果客户端传过来的会话ID有效则尝试恢复上次会话(可用话可跳过交换证书过程),报文包含时间和随机数、会话ID和和从密文族中选择使用的加密方法;
    server将证书发送给client:client接收到证书后按证书声称的证书颁发机构用系统内置的对应证书颁发机构的根证书对server发过来的证书进行验证(证书签名验证、是否是声称的域名的证书、有效期验证等);
    交换秘钥:过程比较复杂,核心是client生成服务端选定的对称加密算法可使用的秘钥,通过证书中的公钥加密后传递给server端,server端接收到后用证书私钥解密,证书中的公钥在此处使用;
    后续client与server之间传输的数据都经过这个秘钥和上方server say-hello选中的密文族方法进行加密,接收后到用同样方法解密,保证数据的安全性;
    加密过程说明:
    1、【浏览器】向服务器发送https请求
    2、【服务器】向CA机构获取证书
    3、【服务器】向浏览器发送数字证书(包含public key)
    4、【浏览器】用预置的CA列表验证证书,生成随机对称秘钥【key】,并使用公钥加密,如有问题会提示风险,
    5、【浏览器】加密后的【key】,发送给【服务器】,作为接下来请求的秘钥
    6、【服务器】用自己的private key解密得到对称秘钥key
    7、【浏览器】使用随机码key进行解密数据
    8、【浏览器】【服务器】使用该秘钥进行通信

    HTTP与HTTPS区别:
    1、http明文传输,https密文传输协议
    2、默认端口http:80端口,https:443端口
    3、https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用
    4、http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全

7、谈谈你对TCP三次握手和四次挥手的理解
    https://blog.csdn.net/m0_38106923/article/details/108292454

8、A、B 机器正常连接后,B 机器突然重启,问 A 此时处于 TCP 什么状态
    A 侧的 TCP 链路状态在未发送任何数据的情况下与等待的时间相关,如果在多个超时值范围以内那么状态为established;如果触发了某一个超时的情况那么视情况的不同会有不同的改变。
    一般情况下不管是 KeepAlive 超时还是内核超时,只要出现超时,那么必然会抛出异常,只是这个异常截获的时机会因编码方式的差异而有所不同。(同步异步 IO,以及有无使用 select、poll、epoll 等 IO 多路复用机制)

9、对称加密和非对称加密
    对称加密:
    加密和解密时使用的是同一个秘钥,这种加密方法称为对称加密,也称为单密钥加密。
    优点:算法公开、计算量小、加密速度快、加密效率高。
    缺点:如果一方的秘钥被泄露,那么加密信息也就不安全了。

    非对称加密
    非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥和私有密钥。
    公开密钥与私有密钥是一对。
    如果用公钥对数据进行加密,只有用对应的私钥才能解密。
    如果用私钥对数据进行加密,只有用对应的公钥才能解密

10、http请求的几种方法和用途
    1、GET方法:发送一个请求来获取服务器上的某一些资源。
    2、POST方法:向URL指定的资源提交数据或附加新的数据。
    3、PUT方法:跟POST方法一样,可以向服务器提交数据,但是它们之间也所有不同,PUT指定了资源在服务器的位置,而POST没有哦。
    4、HEAD方法:指请求页面的部。
    5、DELETE方法:删除服务器上的某资源。
    6、OPTIONS方法:它用于获取当前URL所支持的方法,如果请求成功,在Allow的头包含类似GET,POST等的信息。
    7、TRACE方法:用于激发一个远程的,应用层的请求消息回路。
    8、CONNECT方法:把请求连接转换到TCP/TP通道。

11、http请求get和post方式的区别
    1、GET是从服务器上获取数据;POST是想服务器传送数据;
    2、GET请求数据有大小限制,受浏览器url长度的限制;post无限制;
    3、GET请求的参数会在Url上暴露显示,POST请求参数在Requestbody里,所以相对GET来说,POST安全性较高
    4、GET 请求的静态资源会被浏览器缓存,POST不会被缓存
    5、GET传递的数据类型是文本,POST是文本或者二进制
    6、GET请求被回退时是无害的,POST请求被回退是会被重新再执行一次

12、GET请求方式的长度限制到底是多少?
    IE:对URL的最大限制为2083个字符,若超出这个数字,提交按钮没有任何反应
    Firefox:对Firefox浏览器URL的长度限制为:65536个字符
    Safari:URL最大长度限制为80000个字符
    Opera:URL最大长度限制为190000个字符
    Google(chrome):URL最大长度限制为8182个字符
    Apache(Server):能接受的最大url长度为8192个字符(这个准确度待定???)

13、浏览器是如何渲染页面的?
    解析HTML文件,创建DOM树。自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载)。
    解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式<HTML中的style样式;
    将CSS与DOM合并,构建渲染树(Render Tree)
    布局和绘制,重绘(repaint)和重排(reflow)

14、请解释JSONP的工作原理,以及它为什么不是真正的AJAX
    JSONP 是一种非正式传输协议,允许用户传递一个callback给服务端,然后服务端返回数据时会将这个callback 参数作为函数名来包裹住 JSON 数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

    当GET请求从后台页面返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用后台页面中的一个callback函数。

    为什么它不是真正的Ajax:
            它们的实质不同
            ajax的核心是通过xmlHttpRequest获取非本页内容
            jsonp的核心是动态添加script标签调用服务器提供的js脚本
            jsonp只支持get请求,ajax支持get和post请求

15、什么是同源策略(Same origin policy)?
    同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

    同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

    详情请查看:https://learn-anything.cn/same-origin-policy

    同源策略的作用:
        为了保护用户信息的安全,防止恶意的网络窃取

    什么是同源:
        端口、域名、协议相同
        安全限制具体都阻止了哪些东西不可以被访问:
        ⽆法读取⾮同源策略下的cookie、localstorage
        ⽆法解除⾮同源的dom
        ⽆法向⾮同源的地址发送ajax请求

    跨域访问:
        跨域访问的解决方案是 CORS!(https://learn-anything.cn/cors)
        也可以通过window.postMessage来实现,但不推荐,容易造成安全问题

16、什么是跨域资源共享(CORS)?
    CORS,全称Cross-Origin Resource Sharing,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略(the same-origin security policy)浏览器会禁止这种跨域请求。
    怎么用CORS:CORS 可以配合 token 来防止 CSRF(跨站请求伪造) 攻击

17、什么是跨站请求伪造(CSRF)?
    跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

    简单的说是攻击者通过伪造用户的浏览器的请求,向一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等

    CSRF 攻击攻击原理及过程:
    (1)用户 C 打开浏览器,访问受信任网站 A,输入用户名和密码请求登录网站 A;
    (2)在用户信息通过验证后,网站 A 产生 Cookie 信息并返回给浏览器,此时用户登录网站 A 成功,可以正常发送请求到网站 A;
    (3)用户未退出网站 A 之前,在同一浏览器中,打开一个 TAB 页访问网站 B;
    (4)网站 B 接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点 A;
    (5)浏览器在接收到这些攻击性代码后,根据网站 B 的请求,在用户不知情的情况下携带 Cookie 信息,向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发起的,所以会根据用户 C 的Cookie 信息以 C 的权限处理该请求,导致来自网站 B 的恶意代码被执行。

    如何预防CSRF:
    1、提交验证码:在表单中添加一个随机的数字或字母验证码。通过强制用户和应用进行交互。来有效地遏制CSRF攻击。
    2、Referer Check:检查假设是非正常页面过来的请求,则极有可能是CSRF攻击。
    3、token验证:在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,假设请求中没有 token 或者 token 内容不对,则觉得可能是 CSRF 攻击而拒绝该请求。token必须足够随机。敏感的操作应该使用POST,而不是GET。比如表单提交。
    4、在HTTP头中自己定义属性并验证:这样的方法也是使用 token 并进行验证。这里并非把 token 以參数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自己定义的属性里。通过 XMLHttpRequest 这个类,能够一次性给全部该类请求加上 csrftoken 这个 HTTP 头属性。并把 token 值放入当中。这样攻克了上种方法在请求中添加 token 的不便。同一时候,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用操心 token 会透过 Referer 泄露到其它站点中去。

18、什么是跨站攻击(XXS)?
    跨站攻击,即Cross Site Script Execution(通常简写为XSS)是指攻击者利用网站程序对用户输入过滤不足,输入可以显示在页面上对其他用户造成影响的HTML代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

    如何预防XXS:
        1、HttpOnly防止获取cookie
            在cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击
        2、输入检查(不要相信用户的所有输入)
        3、输出检查(存的时候转义或者编码)

19、cookie 和 token 都存放在 header 中,为什么不会劫持 token
cookie:登录后服务端生成的sessionid,并在http请求里返回到客户端,同时服务端保存
sessionid,以后客户端的每次http请求都带上cookie(sessionid),服务端会获取cookie(sessionid)然后验证用户的身份。所以拿到cookie就拿到了sessionid,就可验证通过。同时浏览器会自动携带cookie;
token:同样是登录后服务端返回一个token,客户端保存起来,在以后http请求里手动的加入到请求头里,服务端根据token 进行身份的校验。浏览器不会自动携带token。
20、如何解决跨域问题
    (1)通过jsonp跨域
    (2)document.domain + iframe跨域
    (3)location.hash + iframe
    (4)window.name + iframe跨域
    (5)postMessage跨域
    (6)跨域资源共享(CORS)
    (7)nginx代理跨域
    (8)nodejs中间件代理跨域
    (9)WebSocket协议跨域

21、浏览器缓存:memory cache、disk cache、强缓存协商缓存等概念
    1、memory cache:Memory Cache 也就是内存中的缓存
        优点:读取速度快
        缺点:一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
        如何触发:当我们访问过页面以后,再次刷新页面,可以发现很多数据都来自于内存缓存

    2、disk cache(css等是disk cache):
        Disk Cache 也就是存储在硬盘中的缓存
        优点:缓存再硬盘中,容量大
        缺点:读取速度慢
        如何触发:根据浏览器请求头

    3、Service Worker:
        Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。
        传输协议必须为 HTTPS
        Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。

    4、Push Cache:
        Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。
        它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂

强缓存:

强缓存不会向服务器发送请求,直接从缓存中读取资源。
强缓存是根据返回头中的 Expires 或者 Cache-Control 两个字段来控制的,都是表示资源的缓存有效时间。
如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。
在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。
协商缓存:

协商缓存是由服务器来确定缓存资源是否使用缓存,即客户端与服务器之间存在一次通信。
协商缓存是根据返回头中的 Last-Modified 或者 Etag,则后续请求则会带上对应的请求字段 If-Modified-Since或者 If-None-Match,若响应头没有 Last-Modified 或者 Etag 字段,则请求头也不会有对应的字段。
在优先级上,服务器校验优先考虑Etag。
HTTP Header里面有关缓存的字段:

        1、Expires:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。
        2、Cache-Control:比如 Cache-Control:max-age=300 时,则代表在这个请求正确返回的5分钟内再次加载资源,就会命中强缓存。
        3、max-age:web中的文件被用户访问(请求)后的存活时间,是个相对的值,相对Request_time(请求时间)
        4、last-modified:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间
        5、ETag:对象(比如URL)的标志值,就一个对象而言,文件被修改,Etag也会修改

    三级缓存原理
        1. 先去内存看,如果有,直接加载
        2. 如果内存没有,择取硬盘获取,如果有直接加载
        3. 如果硬盘也没有,那么就进行网络请求
        4. 加载到的资源缓存到硬盘和内存
        比如:访问图片-> 200 -> 退出浏览器
        再进来-> 200(from disk cache) -> 刷新 -> 200(from memory cache)

22、谈谈垃圾回收机制方式及内存管理
    JavaScript 在定义变量时就完成了内存分配。当不在使用变量了就会被回收,因为其开销比较大,垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

    (1)垃圾回收
        标记清除法:当变量进入环境时,将这个变量标记为'进入环境'。当标记离开环境时,标记为‘离开环境’,离开环境的变量会被回收;
        引用技计数法:跟踪记录每个值被引用的次数,如果没有被引用,就会回收
    (2)内存管理:内存分配=》内存使用=》内存回收

23、介绍一下js的数据类型有哪些,值是如何存储的?
    (1)数据类型
            基本数据类型:undefined、null、Boolean、String、Number、BigInt、Symbol
            引用数据类型:Object

    (2)如何存储
            原始数据类型:直接存储在栈中,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
            引用数据类型:同时存储在栈和堆中,占据空间大,大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实

24、js的数据类型的转换都有哪些?
    (1)转为布尔值:调用Boolean()方法
    (2)转为数字:调用Number()、parseInt()、parseFloat()方法
    (3)转为字符串:调用toString()、String()方法

25、JS中常见的内存泄漏
    1、意外的全局变量
            函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放。

    2、未清除的定时器
            定时器没有清除,它内部引用的变量,不会被释放。

    3、脱离DOM的元素引用
            一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。

    4、持续绑定的事件
            函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。

    5、闭包引起内存泄漏
            比如事件处理回调,导致DOM对象和脚本中对象双向引用。

    6、console.log
            console.log的对象是不能被垃圾回收

26、什么叫优雅降级和渐进增强?
    渐进增强(Progressive Enhancement):
        一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
    优雅降级(Graceful Degradation):
        一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。
    其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。
    区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带

27、请简要描述margin重合问题,及解决方式
    (1)设置padding代替margin
    (2)设置float
    (3)设置overflow
    (4)设置position:absolute 绝对定位
    (5)设置display: inline-block

28、什么是重绘和回流?如何减少重绘与回流?
    注:回流必定会发生重绘,重绘不一定会引发回流。

    1. 浏览器渲染机制
    浏览器采用流式布局模型(Flow Based Layout)
    浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。
    有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
    由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。

    2. 重绘
    由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。

    3. 回流
    回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。大部分的回流将导致页面的重新渲染。

    4. 浏览器优化
    现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。

    主要包括以下属性或方法:
    offsetTop、offsetLeft、offsetWidth、offsetHeight
    scrollTop、scrollLeft、scrollWidth、scrollHeight
    clientTop、clientLeft、clientWidth、clientHeight
    width、height
    getComputedStyle()
    getBoundingClientRect()
    所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。

    5. 减少重绘与回流

    (1)CSS:
    使用 transform 替代 top
    使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流
    避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。
    尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。
    避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。
    应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。

    将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。
    避免使用CSS表达式,可能会引发回流。
    将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。
    CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

    (2)JavaScript:
    避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
    避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
    避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
    对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

29、require和import之间的区别?
    (1)require对应导出的方法是module.exports,import对应的方法是export default/export
    (2)require 是CommonJs的语法,import 是 ES6 的语法标准。
    (3)require是运行运行时加载模块里的所有方法(动态加载),import 是编译的时候调用(静态加载),不管在哪里引用都会提升到代码顶部。
    (4)require 是CommonJs的语法,引入的是的是整个模块里面的对象,import 可以按需引入模块里面的对象
    (5)require 导出是值的拷贝,import 导出的是值的引用

30、栈和堆的区别?
    (1)申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
    (2)申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
    (3)申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
    (4)存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
    (5)底层不同。栈是连续的空间,而堆是不连续的空间。
    (6)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
    (7)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

31、关于JS事件冒泡与JS事件代理(事件委托)
    (1)事件冒泡
            当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window,过程就像冒泡泡 。如果在某一层想要中止冒泡,使用 event.stopPropagation() 。
            但是当大量标签大量事件的时候显然不可能为每个元素都加上事件,(事件绑定占用事件,浏览器要跟踪每个事件,占用更多内存。而且并不是所有事件都会被用户使用到)。所以需要事件委托来解决这个问题。

    (2)事件委托
            将事件给最外层的元素,自己不实现逻辑,由最外层元素来代理。(判断事件源,做不同处理

32、什么是事件流?什么是事件冒泡?什么是事件捕获?
            事件流:从页面中接收事件的顺序。也就是说当一个事件产生时,这个事件的传播过程,就是事件流。
            冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
            捕获型事件:事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
            在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。
            注意:IE浏览器用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。

    如何阻止事件冒泡?
            w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true,return false也能阻止冒泡

    如何阻止默认事件?
            w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false,return false也能阻止默认行为

33、响应事件有哪些?
    (1)鼠标单击事件( onclick )
    (2)鼠标经过事件( onmouseover )
    (3)鼠标移开事件( onmouseout )
    (4)光标聚焦事件( onfocus )
    (5)失焦事件( onblur )
    (6)内容选中事件( onselect )
    (7)文本框内容改变事件( onchange )
    (8)加载事件( onload )
    (9)卸载事件( onunload )

34、document.ready和document.onload的区别
    (1)ready表示文档结构已经加载完成(不包含图片等非文字媒体文件) ,onload表示页面包含图片等文件在内的所有元素都加载完成
    (2)ready可以多次使用,而onload只能有一个,如果出现多个的话后面的会自动覆盖前面的函数

35、防抖和节流
    1.防抖(debounce):
        防抖触发高频率事件时n秒后只会执行一次,如果n秒内再次触发,则会重新计算。
        简单概括:每次触发时都会取消之前的延时调用。

    2.节流(thorttle):
        高频事件触发,每次触发事件时设置一个延迟调用方法,并且取消之前延时调用的方法。
        简单概括:每次触发事件时都会判断是否等待执行的延时函数。

    区别:
        (1)降低回调执行频率,节省计算资源。
        (2)防抖和节流本质是不一样的。
        (3)防抖是将多次执行变为最后一次执行
        (4)节流是将多次执行变成每隔一段事件执行
        (5)函数防抖一定连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次。

36、let、const和var区别
    (1)var存在变量提升,let和const不存在变量提升机制
    (2)var允许重复声明,而let和const不允许重复声明
    (3)var不存在暂时性死区,let和const存在暂时性死区
    (4)let和const创建的全局变量没有给window设置对应的属性
    (5)let和const会产生块级作用域
    (6)const声明的同时需要赋值,如果是基础数据类型不能重复赋值,如果是引用数据类型则可以修改内部的值例如对象

37、请解释一下变量声明提升?
    通过var声明的变量会被提升至作用域的顶端。不仅仅是变量,函数声明也一样会被提升。当同一作用域内同时出现变量和函数声明提升时,变量仍然在函数前面

38、全局作用域中,用 const 和 let 声明的变量不在 window 上,那到底在哪里?如何去获取?
    在ES5中,顶层对象的属性和全局变量是等价的,var 命令和 function 命令声明的全局变量,自然也是顶层对象。
    但ES6规定,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性,但 let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
    在全局作用域中,用 let 和 const 声明的全局变量并没有在全局对象中,只是一个块级作用域(Script)中
    
    怎么获取?在定义变量的块级作用域中就能获取啊,既然不属于顶层对象,那就不加 window(global)呗

39、什么是闭包以及闭包的特点?
    闭包是什么?
    闭包就是能够读取其他函数内部变量的函数。
    由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。
    所以,闭包的本质就是在一个函数内部创建另一个函数

    闭包有3个特性:
    ①函数嵌套函数;
    ②函数内部可以引用函数外部的参数和变量;
    ③参数和变量不会被垃圾回收机制回收.

    闭包的好处:
    ①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突;
    ②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存);
    ③匿名自执行函数可以减少内存消耗

    闭包的坏处:
    ①其中一点上面已经有体现了,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
    ②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

40、Cookie,sessionStorage,localStorage解释及其区别
    (1)Cookie
            Cookie 是一些数据,由服务器生成,发送给浏览器,一旦用户从该网站或服务器退出,Cookie 就存储在用户本地的硬盘上,下一次请求同一网站时会把该cookie发送给服务器。Cookie的作用就是用于解决“如何记录客户端的用户信息”。
            可以使用 document.cookie 属性来创建 、读取、及删除 cookie。
            cookie的内容主要包括:名字name,值value,过期时间expires,路径path和域domain。路径和域一起构成cookie的作用范围。一般cookie储存在内存里,若设置了过期时间则储存在硬盘里,浏览器页面关闭也不会失效,直到设置的过期时间后才失效。若不设置cookie的过期时间,则有效期为浏览器窗口的会话期间,关闭浏览器窗口就失效。

    (2)sessionStorage
            sessionStorage顾名思义,是在当前会话下有效,引入了一个“浏览器窗口的概念”,sessionStorage是在同源的同窗口中,始终存在的数据,只要浏览器不关闭,即使是刷新或者进入同源的另一个页面,数据仍在。同时打开“独立”的窗口,即使是同一个页面,sessionStorage的对象也是不同的。关闭窗口后sessionStorage就会被销毁。
            可以使用 sessionStorage.setItem、sessionStorage.getItem、sessionStorage.removeItem 来创建 、读取、及删除 sessionStorage。

    (3)localStorage
            localStorage的生命周期是永久,除非手动去清除,否则永远都存在,他的储存大小是5MB,仅在客户端浏览器上储存,不参与服务器的通信。
            可以使用 localStorage.setItem、localStorage.getItem、localStorage.removeItem 来创建 、读取、及删除 localStorage。

    (4)Cookie,sessionStorage,localStorage的区别:
            存储大小:Cookie 是4KB,Storage是5M;
            有效期:Cookie可以设置有效期,超过有效期自动清除;localStorage永久存储,除非手动清除;sessionStorage是会话缓存,关闭浏览器就会清除;
            存储位置:Cookie会发送到服务器端,存储在内存中,Storage只存储在浏览器端;
            作用域不同:sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;Cookie也是在所有同源窗口中都是共享的
            存储内容: Cookie只能保存字符串类型,以文本的方式。Storage通过能支持任何类型的对象(Storage中可含有多个对象)
            API:Storage的API接口使用更方便

41、typeof 与 instanceof 区别
    typeof 与 instanceof都是判断数据类型的方法,区别如下:
    typeof 会返回一个变量的基本类型,instanceof 返回的是一个布尔值
    instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型
    而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断

42.数据类型检测的方式有哪些

        1.typeof基本数据类型 

        2 instanceof可以正确判断对象的类型 

        3constructor有两个作用,一是判断数据的类型,二是对象实例通过 

        4Object.prototype.toString.call()使用 Object 对象的原型方法 toString 来判断数据类型:


42、3中判断数组的方法,请分别介绍它们之间的区别和优劣:Object.prototype.toString.call() 、 instanceof 以及 Array.isArray()
        https://blog.csdn.net/qq_41257129/article/details/100075432

43、分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景。
    结构:

    display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击,
    visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击
    opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
    继承:

    display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。
    visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
    性能:

    displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大
    visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容
    opacity: 0 : 修改元素会造成重绘,性能消耗较少
44、深度优先遍历和广度优先遍历,如何实现?
    深度优先遍历(DFS)
        顾名思义,深度优先遍历就是找准一条路不停深入的搜索方法,当发现这条路走不通的时候就会回退到上一个探索的节点,如果上一个节点存在没有探索的分支,便继续探索若没有则继续回退。深度优先遍历就有点像二叉树中的前序、中序和后序遍历。
        深度优先遍历的关键就在于如何找到已经探索过节点的上一个节点,也就是如何回溯。

    广度优先遍历(BFS)
        广度优先遍历是首先把起点相邻的几个点探索完成,然后去探索距离起点稍远一些(隔一层)的点,然后再去玩探索距离起点更远一些(隔两层)的点… 是一层一层的向外探索。这点就很像二叉树的层序遍历。

45、有哪些遍历数组方法
    for、forEach、for...in、for...of、map、filter、reduce、every、some

46、forEach、for...in 、for...of三者的区别
    (1)forEach遍历数组,但不能使用break、continue和return语句
    (2)for…in是用来循环带有字符串key的对象的方法。实际是为循环”enumerable“(可枚举)对象而设计的。Js基本数据类型自带的原型属性不可枚举,通过Object.defineProperty0方法指定enumeralbe为false的属性不可枚举。
    (3)for...in循环出的是key,for…of循环出的是value。
    (4)for…of数组对象都可以遍历,它是ES6中新增加的语法。一个数据结构只有部署了 Symbol.iterator 属性, 才具有 iterator接口可以使用 for…of循环。

    (5)for...in循环主要是为遍历对象而设计的,不适用于遍历数组;

    (6)for...of适用遍历数组/字符串/map/set等有迭代器对象的集合,但是不能遍历普通对象,for…of遍历对象需要通过和Object.keys()

    哪些数据结构部署了 Symbol.iteratoer属性了呢?
        Array、Map、Set、String、arguments对象、Nodelist对象,就是获取的dom列表集合

47、介绍下 Set、Map、WeakSet 和 WeakMap 的区别?
    1.set:
        set表示集合,可以存储原始值和对象引用,存储的数据必须是唯一值
        size()、add()、delete()、has()、clear()

    2.map:
        map表示字典,用键值对的形式存放数据,键和值可以是原始值和对象引用
        size()、set(key,value)、get(key)、has(key)、delet(key)、clear()

    3.weakset
        weakset是弱集合,存储的数据只能是对象,对对象的引用是弱引用
        在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收
        不可枚举
    4.weakmap
        weakmap是弱字典,以键值对形式存放,键只能是对象,对对象的引用是弱引用
        在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收
        不可枚举

48、使用Set数组去重
    Array.from(new Set(arr))

49、Map和Object的区别
    (1)意外的键:Map默认不包含任意键,只包含插入的键值;Object有一个原型、原型链的键名可能和自己在对象上设置的键名发生冲突;
    (2)键的类型:Map键的类型是任意的;Object键的类型是string和symbol;
    (3)键的顺序:Map有序的,迭代的时候以其插入的顺序返回键值;Object无序的;
    (4)size:Map的长度可以通过size属性获取;Object需要手动计算;
    (5)迭代:Map是可迭代的;Object需要通过获取键来迭代;
    (6)性能:Map在频繁增删键值对的场景下表现更好;Object在频繁添加和删除键值对的场景下未作出优化;

50、Object.assgin()、扩展运算符(三点运算符)的区别
    相同点:
        1.均可以实现对象的合并
        2.将源对象的所有可枚举属性,复制到目标对象
        3.在复制的过程中出现同名的属性(方法),后边的属性(方法)会覆盖之前的同名属性(方法)
        4.都是浅拷贝(浅拷贝理解为拷贝指向数值的地址或者指向数值的指针,深拷贝理解为拷贝到内存中的具体的数值)

    不同点:
        1.使用方式不同,object.assign(target,source1,source2,source3)可以接收多个参数,第一个参数是目标对象,后面的都是源对象,
        2.扩展运算符直接(...a,...b)

51、原生对象和宿主对象?
    原生对象是ECMAScript规定的对象,所有内置对象都是原生对象,比如Array、 Date、 RegExp等;
    宿主对象是宿主环境比如浏览器规定的对象,用于完善是ECMAScript的执行环境,比如Document、 Location、Navigator等。

52、什么是原型?什么是原型链?
    原型:每个构造函数都有一个原型对象,实例化出来的对象都有一个原型,指向的是构造函数的原型对象,原型对象里面有一个指针constructor,指向的是它的构造函数。所有的原型对象都是Object构造函数的实例。它的原型指的就是Object原型对象,在往上找Object原型对象的原型就是null了。所有的构造函数都是function构造函数的实例,所有构造函数的原型指的就是function原型对象。

    原型链:当在实例化的对象中访问一个属性时,首先会在该对象内部(自身属性)寻找,如找不到,则会向其__proto__指向的原型中寻找,如仍找不到,则继续向原型中__proto__指向的上级原型中寻找,直至找到或Object.prototype.__proto__为止(值为null),这种链状过程即为原型链。

    原型的作用:
        1.数据共享 节约内存内存空间
        2.实现继承

53、js 获取原型的方法?
    (1)Object.getPrototypeOf()
    (2)__proto__
    (3)constructor.prototype

54、for..in 和 object.keys的区别?
    Object.keys不会遍历继承的原型属性
    for...in 会遍历继承的原型属性

55、JS 中 == 和 === 区别是什么?

    https://www.cnblogs.com/bryanfu/p/15063999.html

    (1)对于string,number等基础类型,==和===有区别
            不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等。
            同类型比较,直接进行“值”比较,两者结果一样。

    (2)对于Array,Object等高级类型,==和===没有区别
            进行“指针地址”比较。

    (3)基础类型与高级类型,==和===有区别
            对于==,将高级转化为基础类型,进行“值”比较。因为类型不同,===结果为false。
        示例:
            [] == [] // false
            {} == {} // false
            null == undefined // true(解释:undefined派生自null,所以返回true)
            null === undefined // false

56、Object.is()与比较操作符 "==="、"==”的区别?
    (1)两等号判等,会在比较时进行类型转换;
    (2)三等号判等(判断严格),比较时不进行隐式类型转换,(类型不同则会返回false);
    (3)Object.is 在三等号判等的基础上特别处理了NaN、-0和+0,保证-0和+0不再相同,但Object.is(NaN, NaN)会返回true。Object.is应被认为有其特殊的用途,而不能用它认为它比其它的相等对比更宽松或严格。

    *补充:Object.is() 方法判断两个值是否是相同的值。表示两个参数是否相同的布尔值。

如果下列任何一项成立,则两个值相同:
        两个值都是 undefined
        两个值都是 null
        两个值都是 true 或者都是 false
        两个值是由相同个数的字符按照相同的顺序组成的字符串
        两个值指向同一个对象
        两个值都是数字并且
        都是正零 +0
        都是负零 -0
        都是 NaN
        都是除零和 NaN 外的其它同一个数字

使用示例:
        Object.is(null,undefined) // false
        Object.is(NaN,0/0) // true
        Object.is(-0,-0) // true
        Object.is(0,-0) // false
        Object.is(0,+0) // true
        Object.is(-0,+0) // false
        NaN == NaN // false
        NaN === NaN // false
        -0 === +0 // true

57、深拷贝、浅拷贝、以及如何实现?
    深拷贝和浅拷贝都是针对复杂类型来说的,深拷贝式是层层拷贝,浅拷贝是只拷贝一层。
    浅拷贝:使用object.assign、直接用=赋值只拷贝地址,它是将数据中的所有数据引用下来,指向同一个存放地址,拷贝后的数据修改后,会影响到原数据中的对象数据。
    深拷贝:JSON.parse(JSON. stringify...),递归拷贝每一层对象是内容拷贝,将数据中的所有数据都拷贝下来,对拷贝后的数据进行修改,不会影响到原数据。
    可以使用for...in、扩展运算符...、递归等递归函数实现深拷贝
    递归:递归就是一个函数调用其本身,通过栈来实现。每执行一个函数,就新建一个函数栈。

58、使用JSON.parse(JSON.stringify(obj))深拷贝有哪些缺点?如何递归实现一个深拷贝?
    JSON.parse(JSON.stringify(obj))深拷贝的问题

    1、如果obj里面存在时间对象,JSON.parse(JSON.stringify(obj))之后,时间对象变成了字符串。
    2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象。
    3、如果obj里有函数、undefined、Symbol,序列化后键值对会消失。
    4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null。
    5、JSON.stringify()只能序列化对象的可枚举的自有属性。如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor。
    6、如果对象中存在循环引用的情况也无法正确实现深拷贝。
    7、无法序列化对象的原型链

*除了JSON的方法,还可以使用递归实现深拷贝

59、箭头函数和普通函数的区别
    (1)普通函数
            可以通过bind、call、apply改变this指向
            可以使用new

    (2)箭头函数
            本身没有this指向
            它的this在定义的时候继承自外层第一个普通函数的this
            被继承的普通函数的this指向改变,箭头函数的this指向会跟着改变
            箭头函数外层没有普通函数时,this指向window
            不能通过bind、call、apply改变this指向
            使用new调用箭头函数会报错,因为箭头函数没有constructor
            60、call,apply,bind的相同点和区别?

    相同点:
            都是改变this指向的;
            第一个参数都是this要指向的对象;
            都可以利用后续参数传参;

    不同点:
            call和bind的参数是依次传参,一一对应的;
            但apply只有两个参数,第二个参数为数组;
            call和apply都是对函数进行直接调用,而bind方法返回的仍是一个函数;

61、描述new一个对象的过程?
    (1)创建一个新对象,新对象的隐式原型__proto__指向new的构造函数的显示原型proptotype
    (2)改变this指向,将构造函数的作用域赋给新的对象,并且执行构造函数的代码,为新的对象添加属性
    (3)返回新的对象(return this)

62、什么是js事件循环机制?什么是宏任务和微任务,两者有什么区别?
    执行顺序:调用栈 -> 微任务队列(promise.then、aysnc、await )-> 宏任务队列(setTimeout、ajax、onClick)
    ***promise本身同步,then/catch的回调函数是异步的

    一、事件循环:
    js是单线程的,但是又需要一种机制来处理多个块的执行,并且执行每个块时都调用js引擎,这种机制称为事件循环,与事件绑定概念毫无关系

    二、事件循环分为三部分:
    主线程、宏队列、微队列,所有异步代码都会被丢进宏/微队列

    2.1 主线程

    所有的同步任务都是在主线程里执行的,异步任务可能会在微任务(macro task)或者宏任务(micro task)里面
    同步任务: 指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
    异步任务: 指的是不进入主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

    三、宏任务、微任务、执行过程

    3.1、 JS把异步任务分为宏任务和微任务

    在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务。

    3.1.1、同步代码(js执行/回调栈)

    3.1.2微任务的异步代码(js引擎):
    微任务是由JS发起的任务
    process.nextTick(node)
    promise.then() catch()
    Async/Await
    object.observe、MutaionOBserver
    promise本身同步,then/catch的回调函数是异步的

    3.1.3 宏任务的异步代码(宿主环境):
    宏任务是由宿主环境(浏览器、Node)发起
    script(代码块)
    setTimeout、setInterval,setImmeditate定时器
    I/O
    UI redering

    3.2、主线程只有一个,且执行顺序为:
    主线程代码☞☞ 微任务☞☞宏任务
    如果宏任务里还有微任就继续执行宏任务里的微任务,如果宏任务中的微任务中还有宏任务就在依次进行

    1.先执行主线程
    2. 遇到宏任务放到宏队列
    3. 遇到微任务放到微队列
    4. 主线程执行完毕
    5. 执行微队列,微队列执行完毕
    6. 执行以一次宏队列的任务,执行完毕
    7. 执行微队列,执行完毕
    8. 依次循环

    3.2.1、 简略

    同步代码(执行栈)
    微任务的异步代码(promise.then、aysnc、await等)
    宏任务的异步代码(setTimeout、ajax、onClick)
    再回到事件循环机制(event loop),不阻塞主进程的程序放入调用栈中,压入栈底,执行完了就会弹出,如果是函数,那么执行完函数里所有的内容才会弹出,而阻塞主进程的程序放入任务队列中,他们需要“排队”依次执行。

63、同步和异步的区别
    同步是一直阻塞模式,如果一个请求需要等待回调,那么会一直等待下去,直到返回结果
    异步是非阻塞模式,无需等待回调,可执行下一步的代码
    异步方式:setTimeout/setInterval/Promise/generator/async/await

64、promise有几种状态?如何变化
    三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
    promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换

    状态的表现:
            pending:不会触发then和catch
            fulfilled:会触发后续的then
            rejected:会触发后续的catch
            then正常返回 resolve,如果报错则返回 rejected
            catch正常返回 resolve,如果报错则返回 rejected

65、Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?
    promise构造函数是同步执行,then/catch的回调函数是异步的

66、async 和 promise 的区别
    (1)Async/Await 代码看起来简洁一些,使得异步代码看起来像同步代码
    (2)async await与Promise一样,是非阻塞的。
    (3)async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。

67、ES5 和 ES6 分别有几种方式声明变量
    ES5 有两种:var 和 function
    ES6 有六种:增加四种,let、const、class 和 import
    注意:let、const、class声明的全局变量再也不会和全局对象的属性挂钩。

    1、var
            没有块的概念,可以跨块访问,不能跨函数访问;
            存在变量提升

    2、let
            let声明的的变量只在它所在的代码块有效;
            不存在变量提升。let不会像var那样发生“变量提升”,因此,变量需要先声明后使用,否则报错
            不允许重复声明

    3、const

            一旦声明就必须立即初始化;
            一旦声明,常量值就不能改变(指堆内存中的地址不能改变)
            其他和let一样

    4、function()
            函数声明后不会立即执行,需要调用的时候才会执行;
            对支持es5和es6浏览器环境在块作用域内有一定区别,所以应该避免在块作用域内声明函数。

    5、class
            相比于对象原型的方式更清晰
            更像面向对象编程的语法

    6、import
            import命令接收一对大括号,其里面的变量名必须与被导入模块对外接口的名称相同
            用as关键字可以将输入的变量名重命名
            import命令输入的变量都是只读的
            import命令具有提升效果,会提升到整个模块的头部,首先执行(因为Import命令是在编译阶段执行的,在代码运行之前)
            import是静态执行,不能使用表达式和变量
            import会执行所加载的模块

68、谈谈你对ES6的理解
    (1)新增模板字符串(为JayaScript提供了简单的字符串插值功能)
    (2)箭头函数
    (3)for...of (用来遍历数据一例如数组中的值 。)
    (4)arguments 对象可被不定参数和默认参数完美代替。
    (5)ES6将promise对象纳入规范,提供了原生的Promise对象。
    (6)增加了let和const命令,用来声明变量。
    (7)增加了块级 作用域。
    (8)let命令实际上就增加了块级作用域。
    (9)引入module模块的概念

68. Object.is() 与比较操作符 “===”、“==” 的区别?

使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进
行强制类型转化后再进行比较。
使用三等号(===)进行相等判断时,如果两边的类型不一致时,不
会做强制类型准换,直接返回 false。
使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相
同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN
是相等的。
69.介绍下 Set、Map、WeakSet 和 WeakMap 的区别?
Set —— 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用
WeakSet —— 成员都是对象;成员都是弱引用,可以被垃圾回收机制回收,可以
用来保存 DOM 节点,不容易造成内存泄漏;
Map —— 本质上是键值对的集合,类似集合;可以遍历,方法很多,可以跟各
种数据格式转换。
WeakMap ——只接受对象( null除外)和  Symbol 值作为键名,不接受其他类型的值作为键名。 (null 除外),不接受其他类型的值作为键
名;键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,
此时键名是无效的;不能遍历,方法有 get set has delete
70.ES6- 阮一峰

ES6 入门教程

71.echatrs图样式

https://madeapie.com/#/

series-bar柱状图 - makeapie echarts社区图表可视化案例

72.

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值