前端面试总结

前端面试

一、计算机网络

1、HTTP和HTTPS

HTTP的基本概念

http: 是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议

HTTP工作原理

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。客户端向服务器发送一个请求报文,服务器以一个状态行作为响应。

HTTP请求/响应的步骤
  • 1.客户端连接到Web服务器
  • 2.发送HTTP请求
  • 3.服务器接受请求并返回HTTP响应
  • 4.释放TCP连接
  • 5.客户端(浏览器)解析HTML内容

记忆口诀:连接发送加响应,释放解析整过程。

HTTP 的 5 种方法
  • GET—获取资源
  • POST—传输资源
  • PUT—更新资源
  • DELETE—删除资源
  • HEAD—获取报文首部
GET与POST的区别

1.浏览器回退表现不同 GET在浏览器回退时是无害的,而POST会再次提交请求

2.浏览器对请求地址的处理不同 GET请求地址会被浏览器主动缓存,而POST不会,除非手动设置

3.浏览器对响应的处理不同GET请求参数会被完整的保留在浏览器历史记录里,而POST中的参数不会被保留

4.参数大小不同. GET请求在URL中传送的参数是有长度的限制,而POST没有限制

5.安全性不同. GET参数通过URL传递,会暴露,不安全;POST放在Request Body中,相对更安全

6.针对数据操作的类型不同.GET对数据进行查询,POST主要对数据进行增删改!简单说,GET是只读,POST是写。

HTTP报文的组成成分

请求报文{ 请求行、请求头、空行、请求体 } 请求行:{http方法、页面地址、http协议、http版本} 响应报文{ 状态行、响应头、空行、响应体 }

https 的基本概念

https:是以安全为目标的 HTTP 通道,即 HTTP 下 加入 SSL 层进行加密。

https 协议的作用:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。

http 和 https 的区别?
  • http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。
  • Https 协议需要 ca 证书,费用较高。
  • 使用不同的链接方式,端口也不同,一般,http 协议的端口为 80,https 的端口为 443。
  • http 的连接很简单,是无状态的。

记忆口诀:明文传输超文本,安全等级各不同。CA证书费用高,无状连接端难同。

https工作原理

客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤:

  1. 客户端使用 https url 访问服务器,则要求 web 服务器建立 ssl 链接
  2. web 服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),传输给客户端
  3. 客户端和 web 服务器端开始协商 SSL 链接的安全等级,也就是加密等级。
  4. 客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话密钥,并传送给网站。
  5. web 服务器通过自己的私钥解密出会话密钥
  6. web 服务器通过会话密钥加密与客户端之间的通信
http协议优缺点
  • HTTPS 协议要比 http 协议安全,可防止数据在传输过程中被窃取、改变,确保数据的完整性。
  • https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。
  • https 缓存不如 http 高效,会增加数据开销。
  • SSL 证书也需要钱,功能越强大的证书费用越高。
  • SSL 证书需要绑定 IP,不能再同一个 ip 上绑定多个域名,ipv4 资源支持不了这种消耗。

2、TCP/IP网络模型

TCP/IP模型是互联网的基础,它是一系列网络协议的总称。这些协议可以划分为四层,分别为链路层、网络层、传输层和应用层。

  • 链路层:负责封装和解封装IP报文,发送和接受ARP/RARP报文等。
  • 网络层:负责路由以及把分组报文发送给目标网络或主机。
  • 传输层:负责对报文进行分组和重组,并以TCP或UDP协议格式封装报文。
  • 应用层:负责向用户提供应用程序,比如HTTP、FTP、Telnet、DNS、SMTP等。

3、TCP三次握手

  1. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
  2. 第二次握手:服务器收到syn包并确认客户的SYN(ack=j+1),同时也发送一个自己的SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。

4、TCP四次挥手

  1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最 后的数据)。
  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些

5、TCP和UDP的区别

  1. TCP是面向连接的,而UDP是面向无连接的。
  2. TCP仅支持单播传输,UDP 提供了单播,多播,广播的功能。
  3. TCP的三次握手保证了连接的可靠性; UDP是无连接的、不可靠的一种数据传输协议,首先不可靠性体现在无连接上,通信都不需要建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收。
  4. UDP的头部开销比TCP的更小,数据传输速率更高实时性更好

6、HTTP请求跨域问题

  1. 跨域的原理

    跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的。
    同源策略,是浏览器对 JavaScript 实施的安全限制,只要协议、域名、端口有任何一个不同,都被当作是不同的域。
    跨域原理,即是通过各种方式,避开浏览器的安全限制

  2. 解决方案

    最初做项目的时候,使用的是jsonp,但存在一些问题,使用get请求不安全,携带数据较小,后来也用过iframe,但只有主域相同才行,也是存在些问题,后来通过了解和学习发现使用代理和proxy代理配合起来使用比较方便,就引导后台按这种方式做下服务器配置,在开发中使用proxy,在服务器上使用nginx代理,这样开发过程中彼此都方便,效率也高;现在h5新特性还有 windows.postMessage()

    • JSONP
      ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链 接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。

      步骤:

      1. 去创建一个script标签
      2. script的src属性设置接口地址
      3. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
      4. 通过定义函数名去接受返回的数据

      JSONP 的缺点:
      JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。

    • document.domain 基础域名相同 子域名不同

    • window.name 利用在一个浏览器窗口内,载入所有的域名都是共享一个 window.name

    • CORS CORS(Cross-origin resource sharing)跨域资源共享 服务器设置对CORS的支持原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求

    • proxy代理 目前常用方式

    • window.postMessage() 利用h5新特性 window.postMessage()

    • Websocket

7、Cookie、sessionStorage、localStorage 的区别

相同点

  • 存储在客户端

不同点

  • cookie数据大小不能超过4k;sessionStorage和localStorage的存储比cookie大得多,可以达到5M+
  • cookie设置的过期时间之前一直有效;localStorage永久存储,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除
  • cookie的数据会自动的传递到服务器;sessionStorage和localStorage数据保存在本地

8、HTTP状态码及常见状态码

  • 200 OK:客户端请求成功
  • 301 Moved Permanently:所请求的页面已经永久重定向至新的URL
  • 302 Found:所请求的页面已经临时重定向至新的URL
  • 304 Not Modified 未修改。
  • 403 Forbidden:对请求页面的访问被禁止
  • 404 Not Found:请求资源不存在
  • 500 Internal Server Error:服务器发生不可预期的错误原来缓冲的文档还可以继续使用
  • 503 Server Unavailable:请求未完成,服务器临时过载或宕机,一段时间后可恢复正常

9、介绍下304过程

304:如果客户端发送了一个带条件的GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。

10、浏览器的缓存机制 强制缓存 && 协商缓存

浏览器与服务器通信的方式为应答模式,即是:浏览器发起HTTP请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中

  • 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
  • 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

以上两点结论就是浏览器缓存机制的关键,他确保了每个请求的缓存存入与读取,只要我们再理解浏览器缓存的使用规则,那么所有的问题就迎刃而解了。为了方便理解,这里根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强制缓存协商缓存

  • 强制缓存

    强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是 ExpiresCache-Control,其中Cache-Control优先级比Expires高。

    强制缓存的情况主要有三种(暂不分析协商缓存过程),如下:

    1. 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)。
    2. 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存。
    3. 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
  • 协商缓存

    协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,同样,协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。协商缓存主要有以下两种情况:

    1. 协商缓存生效,返回304
    2. 协商缓存失效,返回200和请求结果结果

11、HTTP2.0 的特性

http2.0的特性如下:

1、内容安全,应为http2.0是基于https的,天然具有安全特性,通过http2.0的特性可以避免单纯使用https的性能下降

**2、二进制格式,**http1.X的解析是基于文本的,http2.0将所有的传输信息分割为更小的消息和帧,并对他们采用二进制格式编码,基于二进制可以让协议有更多的扩展性,比如引入了帧来传输数据和指令

**3、多路复用,**这个功能相当于是长连接的增强,每个request请求可以随机的混杂在一起,接收方可以根据request的id将request再归属到各自不同的服务端请求里面,另外多路复用中也支持了流的优先级,允许客户端告诉服务器那些内容是更优先级的资源,可以优先传输,

http3.0 特性如下

  • 连接迁移
  • 无队头阻塞
  • 自定义的拥塞控制
  • 前向安全和前向纠错

12、理解xss,csrf攻击原理以及避免方式

XSS(Cross-Site Scripting跨站脚本攻击)是一种代码注入攻击。攻击者在目标网站上注入恶意代码,当被攻击者登陆网站时就会执行这些恶意代码,这些脚本可以读取 cookie,session tokens,或者其它敏感的网站信息,对用户进行钓鱼欺诈,甚至发起蠕虫攻击等。

CSRFCross-site request forgery跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

XSS避免方式:

  1. url参数使用encodeURIComponent方法转义
  2. 尽量不是有InnerHtml插入HTML内容
  3. 使用特殊符号、标签转义符。
  4. cookie设置httpOnly属性,对用户的输入进行检查,进行特殊字符过滤

CSRF避免方式

  1. 添加验证码
  2. 检查https头部的refer
  3. 使用token
    • 服务端给用户生成一个token,加密后传递给用户
    • 用户在提交请求时,需要携带这个token
    • 服务端验证token是否正确

二、浏览器

1、从输入URL到页面加载的全过程

  1. 首先在浏览器中输入URL
  2. 查找缓存:浏览器先查看浏览器缓存-系统缓存-路由缓存中是否有该地址页面,如果有则显示页面内容。如果没有则进行下一步。
  3. DNS域名解析:浏览器向DNS服务器发起请求,解析该URL中的域名对应的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议
  4. 建立TCP连接:解析出IP地址后,根据IP地址和默认80端口,和服务器建立TCP连接
  5. 发起HTTP请求:浏览器发起读取文件的HTTP请求,,该请求报文作为TCP三次握手的第三次数据发送给服务器
  6. 服务器响应请求并返回结果:服务器对浏览器请求做出响应,并把对应的html文件发送给浏览器
  7. 关闭TCP连接:通过四次挥手释放TCP连接
  8. 浏览器渲染:客户端(浏览器)解析HTML内容并渲染出来,浏览器接收到数据包后的解析流程为:
    • 构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
    • 构建CSS规则树:生成CSS规则树(CSS Rule Tree)
    • 构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
    • 布局(Layout):计算出每个节点在屏幕中的位置
    • 绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。
  9. JS引擎解析过程:调用JS引擎执行JS代码(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链、回收机制等等)

2、浏览器的主要功能

浏览器的主要功能就是向服务器发出请求,在浏览器窗口中展示您选择的网络资源。这里所说的资源一般是指 HTML 文档,也可以是 PDF、图片或其他的类型。资源的位置由用户使用 URI(统一资源标示符)指定。

3、浏览器的主要组成部分是什么?

  1. 用户界面 - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
  2. 浏览器引擎 - 在用户界面和呈现引擎之间传送指令。
  3. 呈现引擎 - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
  4. 网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
  5. 用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
  6. JavaScript 解释器。用于解析和执行 JavaScript 代码。
  7. 数据存储。这是持久层。浏览器需要在硬盘上保存各种数据,

4、浏览器是如何渲染UI的?

  1. 浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree
  2. 与此同时,进行CSS解析,生成Style Rules
  3. 接着将DOM Tree与Style Rules合成为 Render Tree
  4. 接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标
  5. 随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来

5、DOM Tree是如何构建的?

  1. 转码: 浏览器将接收到的二进制数据按照指定编码格式转化为HTML字符串
  2. 生成Tokens: 之后开始parser,浏览器会将HTML字符串解析成Tokens
  3. 构建Nodes: 对Node添加特定的属性,通过指针确定 Node 的父、子、兄弟关系和所属 treeScope
  4. 生成DOM Tree: 通过node包含的指针确定的关系构建出DOM Tree

6、浏览器重绘与重排的区别?

  • 重排/回流(Reflow):当DOM的变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。表现为重新生成布局,重新排列元素。
  • 重绘(Repaint): 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。表现为某些元素的外观被改变

『重绘』不一定会出现『重排』,『重排』必然会出现『重绘』

7、如何触发重排和重绘?

任何改变用来构建渲染树的信息都会导致一次重排或重绘:

  • 添加、删除、更新DOM节点
  • 通过display: none隐藏一个DOM节点-触发重排和重绘
  • 通过visibility: hidden隐藏一个DOM节点-只触发重绘,因为没有几何变化
  • 移动或者给页面中的DOM节点添加动画
  • 添加一个样式表,调整样式属性
  • 用户行为,例如调整窗口大小,改变字号,或者滚动。

8、如何避免重绘或者重排?

  1. 集中改变样式,不要一条一条地修改 DOM 的样式。
  2. 不要把 DOM 结点的属性值放在循环里当成循环里的变量。
  3. 为动画的 HTML 元件使用 fixedabsoultposition,那么修改他们的 CSS 是不会 reflow 的。
  4. 不使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。
  5. 尽量只修改position:absolutefixed元素,对其他元素影响不大
  6. 动画开始GPU加速,translate使用3D变化
  7. 提升为合成层

9、说下进程、线程和协程

进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。

协程,英文Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。

进程和线程的区别与联系

【区别】:

调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位;

并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行;

拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。

系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。但是进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个进程死掉就等于所有的线程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。

【联系】:

一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程;

资源分配给进程,同一进程的所有线程共享该进程的所有资源;

处理机分给线程,即真正在处理机上运行的是线程;

线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

10、进程间的通信方式有哪些

总共有八种,面试中只要能大概答上三四种方式的原理就可以了

1、无名管道:半双工的通信方式,数据只能单向流动且只能在具有亲缘关系的进程间使用

2、高级管道:将另一个程序当作一个新的进程在当前程序进程中启动,则这个进程算是当前程序的子进程,

3、有名管道,:也是半双工的通信方式,但是允许没有亲缘进程之间的通信

4、消息队列:消息队列是有消息的链表,存放在内核中,并由消息队列标识符标识,消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限的缺点

5、信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问,它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源,

6、信号:用于通知接受进程某个事件已经发生

7、共享内存:共享内存就是映射一段能被其他进程所访问的内存。这段共享内存由一个进程创建,但是多个进程可以访问,共享内存是最快的IPC 方式,往往与其他通信机制配合使用

8、套接字:可用于不同机器之间的进程通信

10、浏览器样式兼容

一、CSS初始化

每个浏览器的css默认样式不尽相同,所以最简单有效的方式就是对其进行初始化(覆盖默认样式)

常见 : *{ margin: 0; padding: 0;}

库:normalize.css

二、浏览器私有属性

常用的前缀有:

firefox浏览器 :-moz-

chrome、safari :-webkit-

opera :-o- / -xv-

IE浏览器 :-ms-(目前只有 IE 8+支持)

三、CSS hack(条件hack、属性级hack、选择符级hack)

11、JS垃圾回收机制

  1. 项目中,如果存在大量不被释放的内存(堆/栈/上下文),页面性能会变得很慢。当某些代码操作不能被合理释放,就会造成内存泄漏。我们尽可能减少使用闭包,因为它会消耗内存。

  2. 浏览器垃圾回收机制/内存回收机制:

    浏览器的Javascript具有自动垃圾回收机制(GC:Garbage Collecation),垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

    标记清除:在js中,最常用的垃圾回收机制是标记清除:当变量进入执行环境时,被标记为“进入环境”,当变量离开执行环境时,会被标记为“离开环境”。垃圾回收器会销毁那些带标记的值并回收它们所占用的内存空间。
    谷歌浏览器:“查找引用”,浏览器不定时去查找当前内存的引用,如果没有被占用了,浏览器会回收它;如果被占用,就不能回收。
    IE浏览器:“引用计数法”,当前内存被占用一次,计数累加1次,移除占用就减1,减到0时,浏览器就回收它。

  3. 优化手段:内存优化 ; 手动释放:取消内存的占用即可。

    (1)堆内存:fn = null 【null:空指针对象】

    (2)栈内存:把上下文中,被外部占用的堆的占用取消即可。

  4. 内存泄漏

    在 JS 中,常见的内存泄露主要有 4 种,全局变量、闭包、DOM 元素的引用、定时器

三、html和css

1、HTML5 新特性、语义化

  1. 概念

    HTML5的语义化指的是合理正确的使用语义化的标签来创建页面结构。【正确的标签做正确的事】

  2. 语义化标签

    header nav main article section aside footer

  3. 语义化的优点:

    • 没CSS样式的情况下,页面整体也会呈现很好的结构效果
    • 代码结构清晰,易于阅读,
    • 利于开发和维护 方便其他设备解析(如屏幕阅读器)根据语义渲染网页。
    • 有利于搜索引擎优化(SEO),搜索引擎爬虫会根据不同的标签来赋予不同的权重

2、HTML5新特性有哪些

  • 语义化标签
  • 音视频处理API(audio,video)
  • canvas / webGL
  • 拖拽释放(Drag and drop) API
  • history API
  • requestAnimationFrame
  • 地理位置(Geolocation)API
  • webSocket
  • web存储 localStorage、SessionStorage
  • 表单控件,calendar、date、time、email、url、search

3、CSS 选择器及优先级

选择器

  • id选择器(#myid)
  • 类选择器(.myclass)
  • 属性选择器(a[rel=“external”])
  • 伪类选择器(a:hover, li:nth-child)
  • 标签选择器(div, h1,p)
  • 相邻选择器(h1 + p)
  • 子选择器(ul > li)
  • 后代选择器(li a)
  • 通配符选择器(*)

优先级:

  • !important
  • 内联样式(1000)
  • ID选择器(0100)
  • 类选择器/属性选择器/伪类选择器(0010)
  • 元素选择器/伪元素选择器(0001)
  • 关系选择器/通配符选择器(0000)

带!important 标记的样式属性优先级最高; 样式表的来源相同时: !important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性

4、CSS3新特性

  • 过渡:transition

  • 动画:animation

  • 形状转换:transform

  • 选择器:nth-of-type()

  • 阴影 文字阴影: text-shadow、盒子阴影: box-shadow

  • 边框 border-image

  • 背景

  • 文字

  • 弹性布局、栅格布局、多列布局

  • 媒体查询

5、position 属性的值有哪些及其区别

固定定位 fixed: 元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。Fixed 定 位使元素的位置与文档流无关,因此不占据空间。 Fixed 定位的元素和其他元素重叠。

相对定位 relative: 如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直 或水平位置,让这个元素“相对于”它的起点进行移动。 在使用相对定位时,无论是 否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。

绝对定位 absolute: 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那 么它的位置相对于。absolute 定位使元素的位置与文档流无关,因此不占据空间。 absolute 定位的元素和其他元素重叠。

粘性定位 sticky: 元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。而后,元素定位表现为在跨越特定阈值前为相对定 位,之后为固定定位。

默认定位 Static: 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声 明)。 inherit: 规定应该从父元素继承 position 属性的值。

6、box-sizing属性

box-sizing 规定两个并排的带边框的框,语法为 box-sizing:content-box/border-box/inherit

content-box:宽度和高度分别应用到元素的内容框,在宽度和高度之外绘制元素的内边距和边框。【标准盒子模型】

border-box:为元素设定的宽度和高度决定了元素的边框盒。【IE 盒子模型】

inherit:继承父元素的 box-sizing 值。

7、CSS 盒子模型

CSS 盒模型本质上是一个盒子,它包括:边距,边框,填充和实际内容。CSS 中的盒子模型包括 IE 盒子模型和标准的 W3C 盒子模型。
在标准的盒子模型中,width 指 content 部分的宽度
在 IE 盒子模型中,width 表示 content+padding+border 这三个部分的宽度

故在计算盒子的宽度时存在差异:

标准盒模型: 一个块的总宽度 = width+margin(左右)+padding(左右)+border(左右)

怪异盒模型: 一个块的总宽度 = width+margin(左右)(既 width 已经包含了 padding 和 border 值)

8、BFC(块级格式上下文)

BFC的概念

BFCBlock Formatting Context的缩写,即块级格式化上下文。BFC是CSS布局的一个概念,是一个独立的渲染区域,规定了内部box如何布局, 并且这个区域的子元素不会影响到外面的元素,其中比较重要的布局规则有内部 box 垂直放置,计算 BFC 的高度的时候,浮动元素也参与计算。

BFC的原理布局规则

  • 内部的Box会在垂直方向,一个接一个地放置
  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  • 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反
  • BFC的区域不会与float box重叠
  • BFC是一个独立容器,容器里面的子元素不会影响到外面的元素
  • 计算BFC的高度时,浮动元素也参与计算高度
  • 元素的类型和display属性,决定了这个Box的类型。不同类型的Box会参与不同的Formatting Context

如何创建BFC?

  • 根元素,即HTML元素
  • float的值不为none
  • position为absolute或fixed
  • display的值为inline-block、table-cell、table-caption
  • overflow的值不为visible

BFC的使用场景

  • 去除边距重叠现象
  • 清除浮动(让父元素的高度包含子浮动元素)
  • 避免某元素被浮动元素覆盖
  • 避免多列布局由于宽度计算四舍五入而自动换行

9、让一个元素水平垂直居中

  • 水平居中

    • 对于 行内元素 : text-align: center;

    • 对于确定宽度的块级元素:

      (1)width和margin实现。margin: 0 auto;

      (2)绝对定位和margin-left: margin-left: (父width - 子width)/2, 前提是父元素position: relative

    • 对于宽度未知的块级元素

      (1)table标签配合margin左右auto实现水平居中。使用table标签(或直接将块级元素设值为 display:table),再通过给该标签添加左右margin为auto。

      (2)inline-block实现水平居中方法。display:inline-block和text-align:center实现水平居中。

      (3)绝对定位+transform,translateX可以移动本身元素的50%。

      (4)flex布局使用justify-content:center

  • 垂直居中

    1. 利用 line-height 实现居中,这种方法适合纯文字类
    2. 通过设置父容器 相对定位 ,子级设置 绝对定位,标签通过margin实现自适应居中
    3. 弹性布局 flex :父级设置display: flex; 子级设置margin为auto实现自适应居中
    4. 父级设置相对定位,子级设置绝对定位,并且通过位移 transform 实现
    5. table 布局,父级通过转换成表格形式,然后子级设置 vertical-align 实现。(需要注意的是:vertical-align: middle使用的前提条件是内联元素以及display值为table-cell的元素)。

10、隐藏页面中某个元素的方法

1.opacity:0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定 一些事件,如click 事件,那么点击该区域,也能触发点击事件的

2.visibility:hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已 经绑定的事件 ,隐藏对应元素,在文档布局中仍保留原来的空间(重绘)

3.display:none,把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素。 不显示对应的元素,在文档布局中不再分配空间(回流+重绘)

11、用CSS实现三角符号

/*记忆口诀:盒子宽高均为零,三面边框皆透明。 */
div:after{
    position: absolute;
    width: 0px;
    height: 0px;
    content: " ";
    border-right: 100px solid transparent;
    border-top: 100px solid #ff0;
    border-left: 100px solid transparent;
    border-bottom: 100px solid transparent;
}

12、Flex (弹性布局)

布局的传统解决方案,基于盒状模型,依赖 display 属性 + position 属性 + float 属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。指定容器 display: flex 即可。 简单的分为容器属性和元素属性。

容器的属性:

  • flex-direction:决定主轴的方向(即子 item 的排列方法)flex-direction: row | row-reverse | column | column-reverse;
  • flex-wrap:决定换行规则 flex-wrap: nowrap | wrap | wrap-reverse;
  • flex-flow: .box { flex-flow: || ; }
  • justify-content:对其方式,水平主轴对齐方式
  • align-items:对齐方式,竖直轴线方向
  • align-content

项目的属性(元素的属性):

  • order 属性:定义项目的排列顺序,顺序越小,排列越靠前,默认为 0
  • flex-grow 属性:定义项目的放大比例,即使存在空间,也不会放大
  • flex-shrink 属性:定义了项目的缩小比例,当空间不足的情况下会等比例的缩小,如果 定义个 item 的 flow-shrink 为 0,则为不缩小
  • flex-basis 属性:定义了在分配多余的空间,项目占据的空间。
  • flex:是 flex-grow 和 flex-shrink、flex-basis 的简写,默认值为 0 1 auto。
  • align-self:允许单个项目与其他项目不一样的对齐方式,可以覆盖
  • align-items,默认属 性为 auto,表示继承父元素的 align-items 比如说,用 flex 实现圣杯布局

13、css布局

六种布局方式总结:圣杯布局、双飞翼布局、Flex布局、绝对定位布局、表格布局、网格布局。

14、清除浮动的方式

  • 添加额外标签(设置属性clear:both)

  • 父级添加overflow属性,或者设置高度

  • 建立伪类选择器清除浮动(:after{…;clear:both;})

15、CSS预处理器Sass、Less、Stylus的区别

什么事CSS预处理器?

CSS预处理器是一种语言用来为CSS增加一些变成的特性,无需考虑浏览器兼容问题,例如你可以在CSS中使用变量,简单的程序逻辑、函数等在编程语言中的一些基本技巧,可以让CSS更加简洁,适应性更强,代码更直观等诸多好处 基本语法区别

Sass是以.sass为扩展名,Less是以.less为扩展名,Stylus是以.styl为扩展名 变量的区别

Sass 变量必须是以$开头的,然后变量和值之间使用冒号(:)隔开,和css属性是一样的。 Less 变量是以@开头的,其余sass都是一样的。 Stylus 对变量是没有任何设定的,可以是以$开头或者任意字符,而且变量之间可以冒号,空格隔开,但是在stylus中不能用@开头 三种预处理器都有:嵌套、运算符、颜色函数、导入、继承、混入。Stylus还有一些高级特性。例如循环、判断等

16、 什么是WebSocket?

WebSocket是HTML5中的协议,支持持久连续,http协议不支持持久性连接。 WebSocket是基于Http协议的,或者说借用了Http协议来完成一部分握手,在握手阶段与Http是相同的。

17、说一下HTML5 drag api

dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发,。

darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发。

dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。

dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。

dragleave:事件主体是目标元素,在被拖放元素移出目标元素是触发。

drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。

dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

18、几个很实用的BOM属性对象方法?

什么是Bom? Bom是浏览器对象。有哪些常用的Bom属性呢?

(1)location对象

location.href-- 返回或设置当前文档的URL
location.search – 返回URL中的查询字符串部分。例如 http://www.dreamdu.com/dreamdu.php?id=5&name=dreamdu 返回包括(?)后面的内容?id=5&name=dreamdu
location.hash – 返回URL#后面的内容,如果没有#,返回空
location.host – 返回URL中的域名部分,例如www.dreamdu.com
location.hostname – 返回URL中的主域名部分,例如dreamdu.com
location.pathname – 返回URL的域名后的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
location.port – 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
location.protocol – 返回URL中的协议部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的内容http:
location.assign – 设置当前文档的URL
location.replace() – 设置当前文档的URL,并且在history对象的地址列表中移除这个URL location.replace(url);
location.reload() – 重载当前页面

(2)history对象

history.go() – 前进或后退指定的页面数 history.go(num);
history.back() – 后退一页
history.forward() – 前进一页

(3)Navigator对象

navigator.userAgent – 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串)
navigator.cookieEnabled – 返回浏览器是否支持(启用)cookie

19、说一下web worker

在HTML页面中,如果在执行脚本时,页面的状态是不可响应的,直到脚本执行完成后,页面才变成可响应。web worker是运行在后台的js,独立于其他脚本,不会影响页面你的性能。并且通过postMessage将结果回传到主线程。这样在进行复杂操作的时候,就不会阻塞主线程了。

如何创建web worker:

检测浏览器对于web worker的支持性

创建web worker文件(js,回传函数等)

创建web worker对象

20、Doctype作用?严格模式与混杂模式如何区分?它们有何意义?

Doctype声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严格模式和混杂模式。

严格模式的排版和JS 运作模式是 以该浏览器支持的最高标准运行。

混杂模式,向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。

21、前端优化

降低请求量:合并资源,减少HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。

加快请求速度:预解析DNS,减少域名数,并行加载,CDN 分发。

缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。

渲染:JS/CSS优化,加载顺序,服务端渲染,pipeline。

22、画一条0.5px的线

采用meta viewport的方式

采用border-image的方式

采用transform: scale()的方式

23、link标签和import标签的区别

link属于html标签,而@import是css提供的

页面被加载时,link会同时被加载,而@import引用的css会等到页面加载结束后加载。

link是html标签,因此没有兼容性,而@import只有IE5以上才能识别。

link方式样式的权重高于@import的。

24、 transition和animation的区别

Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition需要触发一个事件才能改变属性,而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from … to,而animation可以一帧一帧的。

四、JavaScript

1、JS中的8种数据类型及区别

包括值类型(基本对象类型)和引用类型(复杂对象类型)

基本类型(值类型): Number(数字),String(字符串),Boolean(布尔),Symbol(符号),null(空),undefined(未定义)在内存中占据固定大小,保存在栈内存中

引用类型(复杂数据类型): Object(对象)、Function(函数)。其他还有Array(数组)、Date(日期)、RegExp(正则表达式)、特殊的基本包装类型(String、Number、Boolean) 以及单体内置对象(Global、Math)等 引用类型的值是对象 保存在堆内存中,栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址。

使用场景:

Symbol:使用Symbol来作为对象属性名(key) 利用该特性,把一些不需要对外操作和访问的属性使用Symbol来定义

2、JS中的数据类型检测方案

1.typeof

优点:能够快速区分基本数据类型

缺点:不能将Object、Array和Null区分,都返回object

2.instanceof

优点:能够区分Array、Object和Function,适合用于判断自定义的类实例对象

缺点:Number,Boolean,String基本数据类型不能判断

3.Object.prototype.toString.call()

优点:精准判断数据类型

缺点:写法繁琐不容易记,推荐进行封装后使用

4.instanceof 的作用

用于判断一个引用类型是否属于某构造函数;

还可以在继承关系中用来判断一个实例是否属于它的父类型。

5.instanceof 和 typeof 的区别:

typeof在对值类型number、string、boolean 、null 、 undefined、 以及引用类型的function的反应是精准的;但是,对于对象{ } 、数组[ ] 、null 都会返回object

3、var && let && const

ES6之前创建变量用的是var,之后创建变量用的是let/const

三者区别

  1. var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
    let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
    const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。
  2. var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。
  3. var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。
  4. 在全局上下文中,基于let声明的全局变量和全局对象GO(window)没有任何关系 ;
    var声明的变量会和GO有映射关系;
  5. let /const/function会把当前所在的大括号(除函数之外)作为一个全新的块级上下文,应用这个机制,在开发项目的时候,遇到循环事件绑定等类似的需求,无需再自己构建闭包来存储,只要基于let的块作用特征即可解决

4、作用域和作用域链

创建函数的时候,已经声明了当前函数的作用域==>当前创建函数所处的上下文。如果是在全局下创建的函数就是[[scope]]:EC(G),函数执行的时候,形成一个全新的私有上下文EC(FN),供字符串代码执行(进栈执行)

定义:简单来说作用域就是变量与函数的可访问范围,由当前环境与上层环境的一系列变量对象组成
1.全局作用域:代码在程序的任何地方都能被访问,window 对象的内置属性都拥有全局作用域。
2.函数作用域:在固定的代码片段才能被访问

作用:作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。

作用域链参考链接一般情况下,变量到 创建该变量 的函数的作用域中取值。但是如果在当前作用域中没有查到,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。

5、闭包的两大作用:保存/保护

  • 闭包的概念

    函数执行时形成的私有上下文EC(FN),正常情况下,代码执行完会出栈后释放;但是特殊情况下,如果当前私有上下文中的某个东西被上下文以外的事物占用了,则上下文不会出栈释放,从而形成不销毁的上下文。 函数执行函数执行过程中,会形成一个全新的私有上下文,可能会被释放,可能不会被释放,不论释放与否,他的作用是:

(1)保护:划分一个独立的代码执行区域,在这个区域中有自己私有变量存储的空间,保护自己的私有变量不受外界干扰(操作自己的私有变量和外界没有关系);

(2)保存:如果当前上下文不被释放【只要上下文中的某个东西被外部占用即可】,则存储的这些私有变量也不会被释放,可以供其下级上下文中调取使用,相当于把一些值保存起来了;

我们把函数执行形成私有上下文,来保护和保存私有变量机制称为闭包

闭包是指有权访问另一个函数作用域中的变量的函数–《JavaScript高级程序设计》

  • 闭包形成的条件

    1. 函数的嵌套
    2. 内部函数引用外部函数的局部变量,延长外部函数的变量生命周期
  • 闭包的用途

    1. 模仿块级作用域
    2. 保护外部函数的变量 能够访问函数定义时所在的词法作用域(阻止其被回收)
    3. 封装私有化变量
    4. 创建模块
  • 闭包应用场景

    闭包的两个场景,闭包的两大作用:保存/保护。 在开发中, 其实我们随处可见闭包的身影, 大部分前端JavaScript 代码都是“事件驱动”的,即一个事件绑定的回调方法; 发送ajax请求成功|失败的回调;setTimeout的延时回调;或者一个函数内部返回另一个匿名函数,这些都是闭包的应用。

  • 闭包的优点:延长局部变量的生命周期

  • 闭包缺点:会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏

6、JS 中 this 的情况

  1. 普通函数调用:通过函数名()直接调用:this指向全局对象window(注意let定义的变量不是window属性,只有window.xxx定义的才是。即let a =’aaa’; this.a是undefined)
  2. 构造函数调用:函数作为构造函数,用new关键字调用时:this指向新new出的对象
  3. 对象函数调用:通过对象.函数名()调用的:this指向这个对象
  4. 箭头函数调用:箭头函数里面没有 this ,所以永远是上层作用域this(上下文)
  5. apply和call调用:函数体内 this 的指向的是 call/apply 方法第一个参数,若为空默认是指向全局对象window。
  6. 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组
  7. 函数作为window内置函数的回调函数调用:this指向window(如setInterval setTimeout 等)

7、call/apply/bind 的区别

相同:

1、都是用来改变函数的this对象的指向的。
2、第一个参数都是this要指向的对象。
3、都可以利用后续参数传参。

**不同:**apply和call传入的参数列表形式不同。apply 接收 arguments,call接收一串参数列表

**bind:**语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8 bind 主要就是将函数绑定到某个对象,bind()会创建一个函数,返回对应函数便于稍后调用;而apply、call则是立即调用。

8、箭头函数的特性

  1. 箭头函数没有自己的this,会捕获其所在的上下文的this值,作为自己的this值
  2. 箭头函数没有constructor,是匿名函数,不能作为构造函数,不能通过new 调用;
  3. 没有new.target 属性。在通过new运算符被初始化的函数或构造方法中,new.target返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是undefined
  4. 箭头函数不绑定Arguments 对象。取而代之用rest参数…解决。由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this),他们的第一个参数会被忽略。(这种现象对于bind方法同样成立)
  5. 箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
  6. 箭头函数没有原型属性 Fn.prototype 值为 undefined
  7. 箭头函数不能当做Generator函数,不能使用yield关键字

9、原型 && 原型链

原型关系:

  • 每个 class都有显示原型 prototype
  • 每个实例都有隐式原型 __proto__
  • 实例的 __proto__ 指向对应 class 的 prototype

原型: 在 JS 中,每当定义一个对象(函数也是对象)时,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象

原型链:函数的原型链对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似。因此可以利用__proto__一直指向Object的原型对象上,而Object原型对象用Object.prototype.__ proto__ = null表示原型链顶端。如此形成了js的原型链继承。同时所有的js对象都有Object的基本防范

特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

10、new运算符的实现机制

  1. 首先创建了一个新的空对象
  2. 设置原型,将对象的原型设置为函数的prototype对象。
  3. 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

11、EventLoop 事件循环

JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,Promise.then,MutationObserver,宏任务的话就是setImmediate setTimeout setInterval

JS运行的环境。一般为浏览器或者Node。 在浏览器环境中,有JS 引擎线程和渲染线程,且两个线程互斥。 Node环境中,只有JS 线程。 不同环境执行机制有差异,不同任务进入不同Event Queue队列。 当主程结束,先执行准备好微任务,然后再执行准备好的宏任务,一个轮询结束。

12、setTimeout、Promise、Async/Await 的区别

  1. **setTimeout:**settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行。

  2. Promise:Promise本身是同步的立即执行函数, 当在executor中执行resolve或者reject的时候, 此时是异步操作, 会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行。

  3. async/await

    async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

13、Async/Await 如何通过同步的方式实现异步

Async/Await就是一个自执行的generate函数。利用generate函数的特性把异步的代码写成“同步”的形式,第一个请求的返回值作为后面一个请求的参数,其中每一个参数都是一个promise对象.

14、介绍节流防抖原理、区别以及应用

节流:事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。

防抖:多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!

使用场景
节流:滚动加载更多、搜索框搜的索联想功能、高频点击、表单重复提交……
防抖:搜索框搜索输入,并在输入完以后自动搜索、手机号,邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染。

15、ES6语法的新增特性有哪些

(1)let关键字,声明变量
(2)const关键字,声明常量
(3)模板字符串
(4)箭头函数
(5)对象和数组解构
(6)数据类型Symbol
(7)Set集合和Map集合
(8)Promise对象
(9)引入class关键字

16、如何解决异步回调地狱

`promise、generator、async/await`

17、什么是事件流:

事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段:

事件捕获阶段、处于目标阶段、事件冒泡阶段

addEventListener:addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

18、说一下事件委托

简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。

19、说一下图片的懒加载和预加载

预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。

懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。

20、异步加载js的方法

defer:只支持IE如果您的脚本不会改变文档的内容,可将 defer 属性加入到

async,HTML5属性仅适用于外部脚本,并且如果在IE中,同时存在defer和async,那么defer的优先级比较高,脚本将在页面完成时执行。

21、eval是做什么的

它的功能是将对应的字符串解析成js并执行,应该避免使用js,因为非常消耗性能(2次,一次解析成js,一次执行)

22、简单的实现一个promise

23、数组去重

法一:indexOf循环去重

法二:ES6 Set去重;Array.from(new Set(array))

法三:Object 键值对去重;把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。

24、能来讲讲JS的语言特性吗

运行在客户端浏览器上;

不用预编译,直接解析执行代码;

是弱类型语言,较为灵活;

与操作系统无关,跨平台的语言;

脚本语言、解释性语言

25、暂停死区

在代码块内,使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

26、说一下什么是virtual dom

用JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异 把所记录的差异应用到所构建的真正的DOM树上,视图就更新了。Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。

27、JS中继承实现的几种方式,

1、原型链继承,将父类的实例作为子类的原型,他的特点是实例是子类的实例也是父类的实例,父类新增的原型方法/属性,子类都能够访问,并且原型链继承简单易于实现,缺点是来自原型对象的所有属性被所有实例共享,无法实现多继承,无法向父类构造函数传参。

2、构造继承,使用父类的构造函数来增强子类实例,即复制父类的实例属性给子类,

构造继承可以向父类传递参数,可以实现多继承,通过call多个父类对象。但是构造继承只能继承父类的实例属性和方法,不能继承原型属性和方法,无法实现函数服用,每个子类都有父类实例函数的副本,影响性能

3、实例继承,为父类实例添加新特性,作为子类实例返回,实例继承的特点是不限制调用方法,不管是new 子类()还是子类()返回的对象具有相同的效果,缺点是实例是父类的实例,不是子类的实例,不支持多继承

4、拷贝继承:特点:支持多继承,缺点:效率较低,内存占用高(因为要拷贝父类的属性)无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)

5、组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

6、寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

28、介绍一下promise,及其底层如何实现

Promise是一个对象,保存着未来将要结束的事件,她有两个特征:

1、对象的状态不受外部影响,Promise对象代表一个异步操作,有三种状态,pending进行中,fulfilled已成功,rejected已失败,只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也就是promise名字的由来

2、一旦状态改变,就不会再变,promise对象状态改变只有两种可能,从pending改到fulfilled或者从pending改到rejected,只要这两种情况发生,状态就凝固了,不会再改变,这个时候就称为定型resolved,

五、TS

1、什么是TypeScript? TypeScript是JavaScript的加强版,它给JavaScript添加了可选的静态类型和基于类的面向对象编程,它拓展了JavaScript的语法。

而且TypeScript不存在跟浏览器不兼容的问题,因为在编译时,它产生的都是JavaScript代码。

2、TypeScript 和 JavaScript 的区别是什么? Typescript 是 JavaScript 的超集,可以被编译成 JavaScript 代码。 用 JavaScript 编写的合法代码,在 TypeScript 中依然有效。Typescript 是纯面向对象的编程语言,包含类和接口的概念。

3为什么要用 TypeScript ? TS 在开发时就能给出编译错误, 而 JS 错误则需要在运行时才能暴露。 作为强类型语言,你可以明确知道数据的类型。代码可读性极强,几乎每个人都能理解。 TS 非常流行,被很多业界大佬使用。

4、TypeScript 和 JavaScript 哪个更好? 由于 TS 的先天优势,TS 越来越受欢迎。但是TS 最终不可能取代 JS,因为 JS 是 TS 的核心。

选择 TypeScript 还是 JavaScript 要由开发者自己去做决定。如果你喜欢类型安全的语言,那么推荐你选择 TS。 如果你已经用 JS 好久了,你可以选择走出舒适区学习 TS,也可以选择坚持自己的强项,继续使用 JS。

5、什么是泛型? 泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,使用时再去指定类型的一种特性。 可以把泛型理解为代表类型的参数 // 我们希望传入的值是什么类型,返回的值就是什么类型 // 传入的值可以是任意的类型,这时候就可以用到 泛型

6、TS中的类 TypeScript 是面向对象的 JavaScript。而其中的类描述了所创建的对象共同的属性和方法。

传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但这对于熟悉使用面向对象方式的程序员来说有些棘手,因为他们用的是基于类的继承并且对象是从类构建出来的。

从ECMAScript 2015,也就是ECMAScript 6,JavaScript程序将可以使用这种基于类的面向对象方法。在TypeScript里允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,

7、什么是构造函数,构造函数作用是什么? 构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。而TypeScript的构造函数用关键字constructor来实现。可以通过this(和java/C#一样代表对象实例的成员访问)关键字来访问当前类体中的属性和方法。

8、实例化是什么? 一般情况下,创建一个类后并不能直接的对属性和方法进行引用,必须对类进行实例化,即创建一个对象。TypeScript中用new 关键字创建对象。实例化后通过“.”来访问属性和方法

9、方法重写是什么? 子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写

重写的作用在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。

10、什么是可索引类型接口? 一般用来约束数组和对象

15、TS的学前基础? 因为 TypeScript 是对 JavaScript 的扩展,更准确的说是 ECMAScript。所以,我们学习我们这套 TypeScript 的课程,需要具备 ECMAScript 语言的基础:

熟悉语法基础(变量、语句、函数等基础概念) 掌握内置对象(Array、Date 等)的使用 面向对象基本概念(构造函数、原型、继承)

六、React

1、React.js是 MVVM 框架吗?

React就是Facebook的一个开源JS框架,专注的层面为View层,不包括数据访问层或者那种Hash路由(不过React 有插件支持),与Angularjs,Emberjs等大而全的框架不同,React专注的中心是Component,即组件。React认为一切页面元 素都可以抽象成组件,比如一个表单,或者表单中的某一项。

React可以作为MVVM中第二个V,也就是View,但是并不是MVVM框架。MVVM一个最显著的特征:双向绑定。React没有这个,它是单向数据绑定的。React是一个单向数据流的库,状态驱动视图。react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流,推崇结合immutable来实现数据不可变。

2、hooks用过吗?聊聊react中class组件和函数组件的区别

类组件是使用ES6 的 class 来定义的组件。 函数组件是接收一个单一的 props 对象并返回一个React元素。

关于React的两套API(类(class)API 和基于函数的钩子(hooks) API)。官方推荐使用钩子(函数),而不是类。因为钩子更简洁,代码量少,用起来比较"轻",而类比较"重"。而且,钩子是函数,更符合 React 函数式的本质。

函数一般来说,只应该做一件事,就是返回一个值。 如果你有多个操作,每个操作应该写成一个单独的函数。而且,数据的状态应该与操作方法分离。根据函数这种理念,React 的函数组件只应该做一件事情:返回组件的 HTML 代码,而没有其他的功能。函数的返回结果只依赖于它的参数。不改变函数体外部数据、函数执行过程里面没有副作用。

类(class)是数据和逻辑的封装。 也就是说,组件的状态和操作方法是封装在一起的。如果选择了类的写法,就应该把相关的数据和操作,都写在同一个 class 里面。

类组件的缺点 :

大型组件很难拆分和重构,也很难测试。
业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑。
组件类引入了复杂的编程模式,比如 render props 和高阶组件。
难以理解的 class,理解 JavaScript 中 this 的工作方式。

区别

函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。

1.状态的有无
hooks出现之前,函数组件没有实例没有生命周期没有state没有this,所以我们称函数组件为无状态组件。 hooks出现之前,react中的函数组件通常只考虑负责UI的渲染,没有自身的状态没有业务逻辑代码,是一个纯函数。它的输出只由参数props决定,不受其他任何因素影响。

2.调用方式的不同
函数组件重新渲染,将重新调用组件方法返回新的react元素。类组件重新渲染将new一个新的组件实例,然后调用render类方法返回react元素,这也说明为什么类组件中this是可变的。

3.因为调用方式不同,在函数组件使用中会出现问题
在操作中改变状态值,类组件可以获取最新的状态值,而函数组件则会按照顺序返回状态值

React Hooks(钩子的作用)

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

React Hooks的几个常用钩子:

  1. useState() //状态钩子
  2. useContext() //共享状态钩子
  3. useReducer() //action 钩子
  4. useEffect() //副作用钩子

3、React 组件通信方式

react组件间通信常见的几种情况:

    1. 父组件向子组件通信
    1. 子组件向父组件通信
    1. 跨级组件通信
    1. 非嵌套关系的组件通信

父组件向子组件通信

父组件通过 props 向子组件传递需要的信息。父传子是在父组件中直接绑定一个正常的属性,这个属性就是指具体的值,在子组件中,用props就可以获取到这个值

子组件向父组件通信

props+回调的方式,使用公共组件进行状态提升。子传父是先在父组件上绑定属性设置为一个函数,当子组件需要给父组件传值的时候,则通过props调用该函数将参数传入到该函数当中,此时就可以在父组件中的函数中接收到该参数了,这个参数则为子组件传过来的值

跨级组件通信

即父组件向子组件的子组件通信,向更深层子组件通信。

  • 使用props,利用中间组件层层传递,但是如果父组件结构较深,那么中间每一层组件都要去传递props,增加了复杂度,并且这些props并不是中间组件自己需要的。
  • 使用context,context相当于一个大容器,我们可以把要通信的内容放在这个容器中,这样不管嵌套多深,都可以随意取用,对于跨越多层的全局数据可以使用context实现。

非嵌套关系的组件通信

即没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。

    1. 可以使用自定义事件通信(发布订阅模式),使用pubsub-js
    1. 可以通过redux等进行全局状态管理
    1. 如果是兄弟组件通信,可以找到这两个兄弟节点共同的父节点, 结合父子间通信方式进行通信。
    1. 也可以new一个 Vue 的 EventBus,进行事件监听,一边执行监听,一边执行新增 VUE的eventBus 就是发布订阅模式,是可以在React中使用的;

4、setState 既存在异步情况也存在同步情况

1.异步情况 在React事件当中是异步操作

2.同步情况 如果是在setTimeout事件或者自定义的dom事件中,都是同步的

5、React 事件绑定原理

React并不是将click事件绑在该div的真实DOM上,而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装并交由真正的处理函数运行。这样的方式不仅减少了内存消耗,还能在组件挂载销毁时统一订阅和移除事件。
另外冒泡到 document 上的事件也不是原生浏览器事件,而是 React 自己实现的合成事件(SyntheticEvent)。因此我们如果不想要事件冒泡的话,调用 event.stopPropagation 是无效的,而应该调用 event.preventDefault

6、介绍一下react

React 是一个用于构建用户界面的 JAVASCRIPT 库。React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)

React特点有:

1.声明式设计 −React采用声明范式,可以轻松描述应用。

2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。

3.灵活 −React可以与已知的库或框架很好地配合。

4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。

5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。

6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

7、有了解过react的虚拟DOM吗,虚拟DOM是怎么对比的呢

当然是使用的diff算法,diff算法有三种优化形式:

tree diff:将新旧两颗DOM树按照层级遍历,只对同级的DOM节点进行比较,即同一父节点下的所有子节点,当发现节点已经不存在,则该节点及其子节点会被完全删除,不会进一步比较

component diff:不同组件之间的对比,如果组件类型相同,暂不更新,否则删除旧的组件,再创建一个新的组件,插入到删除组件的位置

element diff:在类型相同的组件内,再继续对比组件内部的元素,

8、react高阶组件知道吗?

高阶组件接收React组件作为参数,并且返回一个新的React组件。高阶组件本质上也是一个函数,并不是一个组件。

9、react-router

9、Redux

七、wepack

1、模块化分类有哪些

A. 浏览器端的模块化

(1)AMD(Asynchronous Module Definition,异步模块定义) 代表产品为:Require.js

(2)CMD(Common Module Definition,通用模块定义) 代表产品为:Sea.js

B. 服务器端的模块化,服务器端的模块化规范是使用CommonJS规范:

  1. 使用require引入其他模块或者包

  2. 使用exports或者module.exports导出模块成员

  3. 一个文件就是一个模块,都拥有独立的作用域

C. ES6模块化,ES6模块化规范中定义:

1.每一个js文件都是独立的模块

2.导入模块成员使用import关键字

3.暴露模块成员使用export关键字

2、 export default 和 exports有什么区别

前者是默认导出,每个模块只能有一个,导入的时候需要用import XX from‘XXX’这种方式

后者是导出,每个模块可以有多个,导入的时候需要用import {XX} from‘XX’的方式

如果在一个模块中没有向外暴露成员,其他模块引入该模块时将会得到一个空对象

3、webpack的作用是什么?

webpack是一个流行的前端项目构建工具,提供了模块化支持,代码压缩混淆,解决兼容问题,性能优化等特性,提高了开发效率和项目的可维护性。

  1. 对代码重新加载翻译。

  2. 合并静态资源,减少io

4、webpack的安装命令是什么?

npm install webpack webpack-cli -D

5、webpack当中的development和production有什么区别

前者为开发模式,代码不会进行压缩,打包速度也更快

后者是生产模式,代码会进行压缩,打包速度相对较慢

6、 如何配置webpack的出口和入口

在webpack.config.js当中设置entry字段,该字段用来配置文件的入口,默认为src下的index.js

在webpack.config.js当中设置output字段,该字段用来配置文件的出口,默认为dist文件下的main.js

7、webpack Loder和plugins区别

loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等

plugins 主要是拓展 webpack 功能

8、webpack怎么打包非js文件

下载文件对应的加载器,然后再webpack.config.js当中配置module的语法规则

9、 webpack如何打包css文件

下载style-loader 和 css-loader,然后再webpack.config.js当中配置语法规则

10、 webpack如何打包less文件

下载less、less-loader、css-loader、style-loader,然后配置语法规则

11、 webpack如何打包图片文件

下载url-loader、file-loader ,配置语法规则

12、webpack打包非vue

①. npm init 初始项目

②. 安装webpack及web -cli

③. 配置打包入口(entry)/出口(output)

④. 设置自动打包

⑤. 下载模块加载器,在webpack.config.js配置语法规则

八、Git

1、如何解决代码冲突问题

  1. 首先将自己的代码提交到本地仓库

  2. 然后将最新的代码从云仓库拉下来

  3. 进行代码合并,如果合并过程当中冲突,手动解决冲突(删除多余的代码或者合并两份代码)

  4. 解决完冲突以后,重新提交到本地,最后上传到云仓库就行了

2、git和SVN有什么区别

  1. 平时只用了git

  2. git是分布式的,svn是集中式的

  3. git仓库可以克隆在本地,svn只可以存储在云上

  4. git支持离线提交,svn只能在线提交

3、git常用的命令有哪些

  1. git status 查看代码状态

  2. git add . 保存代码到暂存区

  3. git commit -m 保存代码到持久区

  4. git pull 将云仓库的代码拉下来

  5. git push 上传代码到云上

  6. git clone 将云仓库代码克隆到本地

  7. git merge XX 合并分支,合并分支的时候只允许在主枝合并

九、Ajax

1、实现一个Ajax

AJAX创建异步对象XMLHttpRequest

操作XMLHttpRequest 对象

(1)设置请求参数(请求方式,请求页面的相对路径,是否异步)

(2)设置回调函数,一个处理服务器响应的函数,使用 onreadystatechange ,类似函数指针

(3)获取异步对象的readyState 属性:该属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会被执行。

(4)判断响应报文的状态,若为200说明服务器正常运行并返回响应数据。

(5)读取响应数据,可以通过 responseText 属性来取回由服务器返回的数据。

2、写出原生Ajax

Ajax能够在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容,实现局部刷新,大大降低了资源的浪费,是一门用于快速创建动态网页的技术,ajax的使用分为四部分:

1、创建XMLHttpRequest对象var xhr = new XMLHttpRequest();

2、向服务器发送请求,使用xmlHttpRequest对象的open和send方法,

3、监听状态变化,执行相应回调函数

var xhr = new XMLHttpRequest();
xhr.open('get','aabb.php',true);
xhr.send(null);
xhr.onreadystatechange = function() {
	if(xhr.readyState==4) {
		if(xhr.status==200) {
			console.log(xhr.responseText);
		}
	}
}

十、jQuery

https://blog.csdn.net/yxorg/article/details/108197076

十一、 BootStrap

https://wwwofai.com/article/11765

十二、NodeJS

https://www.jianshu.com/p/702cee7d5fc0

十三、Axios

https://blog.csdn.net/weixin_40013817/article/details/102931418

十四、W3C标准

https://www.w3cschool.cn/xuexiw3c/xuexiw3c-standards.html

你可能感兴趣的:(学习,前端,面试,http)