前端面试题

1.说一下http和https?

(1)http和https的基本概念 

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

https: 是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 

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

(2)http和https的区别? 

http传输的数据都是未加密的,也就是明文的,网景公司设置了SSL协议来对http协议传输的数据进行加密处理,简单来说https协议是由http和ssl协议构建的可进行加密传输和身份认证的网络协议,比http协议的安全性更高。
主要的区别如下: 

Https协议需要ca证书,费用较高。 

http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。 

使用不同的链接方式,端口也不同,一般而言,http协议的端口为80,https的端口为443 

http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。 

(3)https协议的工作原理 

客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。 

客户使用https url访问服务器,则要求web 服务器建立ssl链接。 

web服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),返回或者说传输给客户端。 

客户端和web服务器端开始协商SSL链接的安全等级,也就是加密等级。 

客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话密钥,并传送给网站。 

web服务器通过自己的私钥解密出会话密钥。 

web服务器通过会话密钥加密与客户端之间的通信。 

(4)https协议的优点 

使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器; 

HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。 

HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。 

谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。 

(5)https协议的缺点 

https握手阶段比较费时,会使页面加载时间延长50%,增加10%~20%的耗电。 

https缓存不如http高效,会增加数据开销。 

SSL证书也需要钱,功能越强大的证书费用越高。 

SSL证书需要绑定IP,不能再同一个ip上绑定多个域名,ipv4资源支持不了这种消耗。

2.tcp三次握手?

客户端和服务端都需要直到各自可收发,因此需要三次握手。

C发起请求连接S确认,也发起连接C确认我们再看看每次握手的作用:第一次握手:S只可以确认 自己可以接受C发送的报文段第二次握手:C可以确认 S收到了自己发送的报文段,并且可以确认 自己可以接受S发送的报文段第三次握手:S可以确认 C收到了自己发送的报文段。

3.tcp和udp的区别?

(1)TCP是面向连接的,udp是无连接的即发送数据前不需要先建立链接。 

(2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。 并且因为tcp可靠,面向连接,不会丢失数据因此适合大数据量的交换。 

(3)TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议等)。 

(4)TCP只能是1对1的,UDP支持1对1,1对多。 

(5)TCP的首部较大为20字节,而UDP只有8字节。 

(6)TCP是面向连接的可靠性传输,而UDP是不可靠的。

4.html5种的drag?

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

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

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

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

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

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

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

5.说一下http2.0?

提升访问速度(可以对于,请求资源所需时间更少,访问速度更快,相比http1.0) 

允许多路复用:多路复用允许同时通过单一的HTTP/2连接发送多重请求-响应信息。改善了:在http1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制(连接数量),超过限制会被阻塞。 

二进制分帧:HTTP2.0会将所有的传输信息分割为更小的信息或者帧,并对他们进行二进制编码 

首部压缩 

服务器端推送

6.iframe是什么?有什么优缺点?

定义:iframe元素会创建包含另一个文档的内联框架

提示:可以将提示文字放在<iframe></iframe>之间,来提示某些不支持iframe的浏览器 

缺点: 

会阻塞主页面的onload事件 

搜索引擎无法解读这种页面,不利于SEO 

iframe和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

7.cookie如何防范xss攻击?

XSS(跨站脚本攻击)是指攻击者在返回的HTML中嵌入javascript脚本,为了减轻这些攻击,需要在HTTP头部配上,set-cookie: 

httponly-这个属性可以防止XSS,它会禁止javascript脚本来访问cookie。 

secure - 这个属性告诉浏览器仅在请求为https的时候发送cookie。 

结果应该是这样的:Set-Cookie=<cookie-value>.....

8.click在ios上有300ms延迟,原因及如何解决?

(1)粗暴型,禁用缩放 

<meta name="viewport" content="width=device-width, user-scalable=no"> 

(2)利用FastClick,其原理是: 

检测到touchend事件后,立刻出发模拟click事件,并且把浏览器300毫秒之后真正出发的事件给阻断掉

9.cookie,sessionstorage,loaclstorage区别?

Cookie和session都可用来存储用户信息,cookie存放于客户端,session存放于服务器端,因为cookie存放于客户端有可能被窃取,所以cookie一般用来存放不敏感的信息,比如用户设置的网站主题,敏感的信息用session存储,比如用户的登陆信息,session可以存放于文件,数据库,内存中都可以,cookie可以服务器端响应的时候设置,也可以客户端通过JS设置cookie会在请求时在http首部发送给客户端,cookie一般在客户端有大小限制,一般为4K, 

下面从几个方向区分一下cookie,localstorage,sessionstorage的区别 

1、生命周期: 

Cookie:可设置失效时间,否则默认为关闭浏览器后失效 

Localstorage:除非被手动清除,否则永久保存 

Sessionstorage:仅在当前网页会话下有效,关闭页面或浏览器后就会被清除 

2、存放数据: 

Cookie:4k左右 

Localstorage和sessionstorage:可以保存5M的信息 

3、http请求: 

Cookie:每次都会携带在http头中,如果使用cookie保存过多数据会带来性能问题 

其他两个:仅在客户端即浏览器中保存,不参与和服务器的通信 

4、易用性: 

Cookie:需要程序员自己封装,原生的cookie接口不友好 

其他两个:即可采用原生接口,亦可再次封装 

5、应用场景: 

从安全性来说,因为每次http请求都回携带cookie信息,这样子浪费了带宽,所以cookie应该尽可能的少用,此外cookie还需要指定作用域,不可以跨域调用,限制很多,但是用户识别用户登陆来说,cookie还是比storage好用,其他情况下可以用storage,localstorage可以用来在页面传递参数,sessionstorage可以用来保存一些临时的数据,防止用户刷新页面后丢失了一些参数。

10.http返回的状态码?

100    Continue    继续。客户端应继续其请求 

101    Switching Protocols    切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 

200    OK    请求成功。一般用于GET与POST请求 

201    Created    已创建。成功请求并创建了新的资源 

202    Accepted    已接受。已经接受请求,但未处理完成 

203    Non-Authoritative Information    非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 

204    No Content    无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 

205    Reset Content    重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 

206    Partial Content    部分内容。服务器成功处理了部分GET请求 

300    Multiple Choices    多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 

301    Moved Permanently    永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 

302    Found    临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI 

303    See Other    查看其它地址。与301类似。使用GET和POST请求查看 

304    Not Modified    未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 

305    Use Proxy    使用代理。所请求的资源必须通过代理访问 

306    Unused    已经被废弃的HTTP状态码 

307    Temporary Redirect    临时重定向。与302类似。使用GET请求重定向 

400    Bad Request    客户端请求的语法错误,服务器无法理解 

401    Unauthorized    请求要求用户的身份认证 

402    Payment Required    保留,将来使用 

403    Forbidden    服务器理解请求客户端的请求,但是拒绝执行此请求 

404    Not Found    服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 

405    Method Not Allowed    客户端请求中的方法被禁止 

406    Not Acceptable    服务器无法根据客户端请求的内容特性完成请求 

407    Proxy Authentication Required    请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 

408    Request Time-out    服务器等待客户端发送的请求时间过长,超时 

409    Conflict    服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 

410    Gone    客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 

411    Length Required    服务器无法处理客户端发送的不带Content-Length的请求信息 

412    Precondition Failed    客户端请求信息的先决条件错误 

413    Request Entity Too Large    由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 

414    Request-URI Too Large    请求的URI过长(URI通常为网址),服务器无法处理 

415    Unsupported Media Type    服务器无法处理请求附带的媒体格式 

416    Requested range not satisfiable    客户端请求的范围无效 

417    Expectation Failed    服务器无法满足Expect的请求头信息 

500    Internal Server Error    服务器内部错误,无法完成请求 

501    Not Implemented    服务器不支持请求的功能,无法完成请求 

502    Bad Gateway    作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 

503    Service Unavailable    由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 

504    Gateway Time-out    充当网关或代理的服务器,未及时从远端服务器获取请求 

505    HTTP Version not supported    服务器不支持请求的HTTP协议的版本,无法完成处理

11.前端优化?

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

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

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

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

12.get和post区别?

get参数通过url传递,post放在request body中。 

get请求在url中传递的参数是有长度限制的,而post没有。 

get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。 

get请求只能进行url编码,而post支持多种编码方式

get请求会浏览器主动cache,而post支持多种编码方式。 

get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。 

GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 

GET产生一个TCP数据包;POST产生两个TCP数据包。

13.http支持的方法?

GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT

14.如何画一个三角形,正方体,旋转硬币?

三角形

div {
width:0px;
height:0px;
border-top:10px solid red;
border-right:10px solid transparent;
border-bottom:10px solid transparent;
border-left:10px solid transparent;
}

 正方体

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>perspective</title>
<style>
.wrapper{
width: 50%;
float: left;
}
.cube{
font-size: 4em;
width: 2em;
margin: 1.5em auto;
transform-style:preserve-3d;
transform:rotateX(-35deg) rotateY(30deg);
}
.side{
position: absolute;
width: 2em;
height: 2em;
background: rgba(255,99,71,0.6);
border: 1px solid rgba(0,0,0,0.5);
color: white;
text-align: center;
line-height: 2em;
}
.front{
transform:translateZ(1em);
}
.bottom{
transform:rotateX(-90deg) translateZ(1em);
}
.top{
transform:rotateX(90deg) translateZ(1em);
}
.left{
transform:rotateY(-90deg) translateZ(1em);
}
.right{
transform:rotateY(90deg) translateZ(1em);
}
.back{
transform:translateZ(-1em);
}
</style>
</head>
<body>
<div class="wrapper w1">
<div class="cube">
<div class="side front">1</div>
<div class="side back">6</div>
<div class="side right">4</div>
<div class="side left">3</div>
<div class="side top">5</div>
<div class="side bottom">2</div>
</div>
</div>
<div class="wrapper w2">
<div class="cube">
<div class="side front">1</div>
<div class="side back">6</div>
<div class="side right">4</div>
<div class="side left">3</div>
<div class="side top">5</div>
<div class="side bottom">2</div>
</div>
</div>
</body>
</html>

 旋转硬币

#euro {
width: 150px;
height: 150px;
margin-left: -75px;
margin-top: -75px;
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
animation: spin 2.5s linear infinite;
}
.back {
background-image: url("/uploads/160101/backeuro.png");
width: 150px;
height: 150px;
}
.middle {
background-image: url("/uploads/160101/faceeuro.png");
width: 150px;
height: 150px;
transform: translateZ(1px);
position: absolute;
top: 0;
}
.front {
background-image: url("/uploads/160101/faceeuro.png");
height: 150px;
position: absolute;
top: 0;
transform: translateZ(10px);
width: 150px;
}
@keyframes spin {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(360deg);
}
}

15.html5新增的元素?

首先html5为了更好的实践web语义化,增加了header,footer,nav,aside,section等语义化标签,在表单方面,为了增强表单,为input增加了color,email , data , range等类型,在存储方面,提供了sessionStorage,localStorage,和离线存储,通过这些存储方式方便数据在客户端的存储和获取,在多媒体方面规定了音频和视频元素audio和vedio,另外还有地理定位,canvas画布,拖放,多线程编程的web worker和websocket协议。

16.在地址栏输入一个url,到这个页面呈现出来,中间会发生什么?

输入url后,首先需要找到这个url域名的服务器ip,为了寻找这个ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录,如果没有则查询DNS服务器,得到服务器的ip地址后,浏览器根据这个ip以及相应的端口号,构造一个http请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个http请求封装在一个tcp包中,这个tcp包会依次经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的html给浏览器,因为html是一个树形结构,浏览器根据这个html来构建DOM树,在dom树的构建过程中如果遇到JS脚本和外部JS连接,则会停止构建DOM树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐JS代码应该放在html代码的后面,之后根据外部样式,内部样式,内联样式构建一个CSS对象模型树CSSOM树,构建完成后和DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为none的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是4-6个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的区别在于Cache-Control使用相对时间,Expires使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先 查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次 响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置ETag则直接验证Last-Modified,再决定是否返回304。

DNS解析 

TCP连接 

发送HTTP请求 

服务器处理请求并返回HTTP报文 

浏览器解析渲染页面 

连接结束

17.cache-control的值有哪些?

cache-control是一个通用消息头字段被用于HTTP请求和响应中,通过指定指令来实现缓存机制,这个缓存指令是单向的,常见的取值有private、no-cache、max-age、must-revalidate等,默认为private。

18.csrf和xss的网络攻击及规范?

CSRF:跨站请求伪造,可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶意请求,比如用户登录了一个网站后,立刻在另一个tab页面访问量攻击者用来制造攻击的网站,这个网站要求访问刚刚登陆的网站,并发送了一个恶意请求,这时候CSRF就产生了,比如这个制造攻击的网站使用一张图片,但是这种图片的链接却是可以修改数据库的,这时候攻击者就可以以用户的名义操作这个数据库,防御方式的话:使用验证码,检查https头部的refer,使用token 

XSS:跨站脚本攻击,是说攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻击,比如获取cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的话不存储在数据库中,往往表现为将攻击代码放在url地址的请求参数中,防御的话为cookie设置httpOnly属性,对用户的输入进行检查,进行特殊字符过滤。

19.介绍http协议(特征)?

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

20.描述一下xss和crsf攻击,防御方法?

XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染DOM树的过程成发生了不在预期内执行的JS代码时,就发生了XSS攻击。大多数XSS攻击的主要方式是嵌入一段远程或者第三方域上的JS代码。实际上是在目标网站的作用域下执行了这段js代码。 

CSRF(Cross Site Request Forgery,跨站请求伪造),字面理解意思就是在别的站点伪造了一个请求。专业术语来说就是在受害者访问一个网站时,其 Cookie 还没有过期的情况下,攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而形成 CSRF 攻击。 

XSS防御的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码。也就是对提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的XSS攻击。 

防御CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

21.html5和css3的新属性?

html5: 

1)标签增删 

8个语义元素 header section footer aside nav main article figure 

内容元素mark高亮 progress进度 

新的表单控件calander date time email url search 

新的input类型 color date datetime datetime-local email 

移除过时标签big font frame frameset 

2)canvas绘图,支持内联SVG。支持MathML 

3)多媒体audio video source embed track 

4)本地离线存储,把需要离线存储在本地的文件列在一个manifest配置文件 

5)web存储。localStorage、SessionStorage

css3: 

CSS3边框如border-radius,box-shadow等;CSS3背景如background-size,background-origin等;CSS3 2D,3D转换如transform等;CSS3动画如animation等。

22.web性能优化?

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

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

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

23.post和get区别?

GET - 从指定的资源请求数据。 

POST - 向指定的资源提交要被处理的数据。 

GET:不同的浏览器和服务器不同,一般限制在2~8K之间,更加常见的是1k以内。 

GET和POST的底层也是TCP/IP,GET/POST都是TCP链接。 

GET产生一个TCP数据包;POST产生两个TCP数据包。 

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

24.link标签和import标签的区别?

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

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

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

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

25.垂直居中的方法?

(1)margin:auto法

定位为上下左右为0,margin:0可以实现脱离文档流的居中. 

(2)margin负值法

补充:其实这里也可以将marin-top和margin-left负值替换成,
transform:translateX(-50%)和transform:translateY(-50%) 

(3)table-cell(未脱离文档流的) 

设置父元素的display:table-cell,并且vertical-align:middle,这样子元素可以实现垂直居中。

(4)利用flex 

将父元素设置为display:flex,并且设置align-items:center;justify-content:center;

26.多行元素的文本省略号?

display: -webkit-box
-webkit-box-orient:vertical
-webkit-line-clamp:3
overflow:hidden
27.position属性比较?
固定定位fixed: 

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

相对定位relative: 

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

绝对定位absolute: 

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

粘性定位sticky: 

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

默认定位Static: 

默认值。没有定位,元素出现在正常的流中(忽略top, bottom, left, right 或者 z-index 声明)。 

inherit: 

规定应该从父元素继承position 属性的值。

28.浮动清除?

方法一:使用带clear属性的空元素 

在浮动元素后使用一个空元素如<div class="clear"></div>,并在CSS中赋予.clear{clear:both;}属性即可清理浮动。亦可使用<br class="clear" />或<hr class="clear" />来进行清理。 

方法二:使用CSS的overflow属性 

给浮动元素的容器添加overflow:hidden;或overflow:auto;可以清除浮动,另外在 IE6 中还需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。 

在添加overflow属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动的效果。 

方法三:给浮动的元素的容器添加浮动 

给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影响布局,不推荐使用。 

方法四:使用邻接元素处理 

什么都不做,给浮动元素后面的元素添加clear属性。 

方法五:使用CSS的:after伪元素 

结合:after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。 

给浮动元素的容器添加一个clearfix的class,然后给这个class添加一个:after伪元素实现元素末尾添加一个看不见的块元素(Block element)清理浮动。

29.了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有哪些方法?

DOM的变化影响到了预算内宿的几何属性比如宽高,浏览器重新计算元素的几何属性,其他元素的几何属性也会受到影响,浏览器需要重新构造渲染书,这个过程称之为重排,浏览器将受到影响的部分重新绘制在屏幕上 的过程称为重绘,引起重排重绘的原因有: 

添加或者删除可见的DOM元素, 

元素尺寸位置的改变 

浏览器页面初始化, 

浏览器窗口大小发生改变,重排一定导致重绘,重绘不一定导致重排, 

减少重绘重排的方法有: 

不在布局信息改变时做DOM查询, 

使用csstext,className一次性改变属性 

使用fragment 

对于多次重排的元素,比如说动画。使用绝对定位脱离文档流,使其不影响其他元素

30.css布局?

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

圣杯布局是指布局从上到下分为header、container、footer,然后container部分定为三栏布局。这种布局方式同样分为header、container、footer。圣杯布局的缺陷在于 center 是在 container 的padding中的,因此宽度小的时候会出现混乱。 

双飞翼布局给center 部分包裹了一个 main 通过设置margin主动地把页面撑开。 

Flex布局是由CSS3提供的一种方便的布局方式。 

绝对定位布局是给container 设置position: relative和overflow: hidden,因为绝对定位的元素的参照物为第一个postion不为static的祖先元素。 left 向左浮动,right 向右浮动。center 使用绝对定位,通过设置left和right并把两边撑开。 center 设置top: 0和bottom: 0使其高度撑开。 

表格布局的好处是能使三栏的高度统一。 

网格布局可能是最强大的布局方式了,使用起来极其方便,但目前而言,兼容性并不好。网格布局,可以将页面分割成多个区域,或者用来定义内部元素的大小,位置,图层关系。

31.get请求传参长度的误区?

误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。 

实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点: 

HTTP 协议 未规定 GET 和POST的长度限制 

GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度 

不同的浏览器和WEB服务器,限制的最大长度不一样 

要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte

32.闭包?

闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。

33.如何解决异步回调地狱?

promise、generator、async/await

34.js的new操作符做了哪些事情?

new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。

35.改变函数内部this指针的指向函数(bind,apply,call的区别)

通过apply和call改变函数的this指向,他们两个函数的第一个参数都是一样的表示要改变指向的那个对象,第二个参数,apply是数组,而call则是arg1,arg2...这种形式。通过bind改变this作用域会返回一个新的函数,这个函数不会马上执行。

36.js的各种位置?

clientHeight:表示的是可视区域的高度,不包含border和滚动条

offsetHeight:表示可视区域的高度,包含了border和滚动条 

scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。 

clientTop:表示边框border的厚度,在未指定的情况下一般为0 

scrollTop:滚动后被隐藏的高度,获取对象相对于由offsetParent属性指定的父坐标(css定位的元素或body元素)距离顶端的高度。

37.ajax解决浏览器缓存问题?

在ajax发送请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。

在ajax发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。

在URL后面加上一个随机数: "fresh=" + Math.random()。

在URL后面加上时间搓:"nowtime=" + new Date().getTime()。

如果是使用jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录。

38.eval是做什么的?

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

39.将原生ajax封装成promise?

var  myNewAjax=function(url){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open('get',url);
xhr.send(data);
xhr.onreadystatechange=function(){
if(xhr.status==200&&readyState==4){
var json=JSON.parse(xhr.responseText);
resolve(json)
}else if(xhr.readyState==4&&xhr.status!=200){
reject('error');
}
}
})
}

 40.js监听对象属性的改变?

我们假设这里有一个user对象

(1)在ES5中可以通过Object.defineProperty来实现已有属性的监听

Object.defineProperty(user,'name',{
set:function(key,value){
}
})

缺点:如果id不在user对象中,则不能监听id的变化 

(2)在ES6中可以通过Proxy来实现

var  user = new Proxy({},{
set:function(target,key,value,receiver){
}
})

 这样即使有属性在user中不存在,通过user.id来定义也同样可以这样监听这个属性的变化哦

41.如何实现一个私有变量,用getName方法可以访问,不能直接访问?

(1)通过defineProperty来实现

obj={
name:yuxiaoliang,
getName:function(){
return this.name
}
}
object.defineProperty(obj,"name",{})

 (2)通过函数的创建形式

function product(){
var name='yuxiaoliang';
this.getName=function(){
return name;
}
}
var obj=new product();

 42.js判断类型?

typeof(),instanceof,Object.prototype.toString.call()等

43.数组常用的方法?

push(),pop(),shift(),unshift(),splice(),sort(),reverse(),map()等

44.数组去重?

法一:indexOf循环去重 

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

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

45.闭包有什么用?

(1)什么是闭包: 

闭包是指有权访问另外一个函数作用域中的变量的函数。 

闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。 

(2)为什么要用: 

匿名自执行函数:我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。 

结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。 

封装:实现类和继承等。

46.去除字符串的首尾空格?

使用正则(^\s*)|(\s*$)即可

47.js语言的特性?

运行在客户端浏览器上; 

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

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

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

脚本语言、解释性语言

48.如何判断一个数组?

Object.prototype.call.toString()
instanceof
49.typeof加一个限制条件达到判断条件?
typeof只能判断是object,可以判断一下是否拥有数组的方法
50.js基本数据类型?
基本数据类型:undefined、null、number、boolean、string、symbol
51.跨域的原理?
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制,那么只要协议、域名、端口有任何一个不同,都被当作是不同的域。跨域原理,即是通过各种方式,避开浏览器的安全限制。
52.angularjs双向绑定原理?
Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ng-bind,ng-show等或是{{}})。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。 

Angular中在view上声明的事件指令,如:ng-click、ng-change等,会将浏览器的事件转发给$scope上相应的model的响应函数。等待相应函数改变model,紧接着触发脏检查机制刷新view。 

watch表达式:可以是一个函数、可以是$scope上的一个属性名,也可以是一个字符串形式的表达式。$watch函数所监听的对象叫做watch表达式。watcher函数:指在view上的指令(ngBind,ngShow、ngHide等)以及{{}}表达式,他们所注册的函数。每一个watcher对象都包括:监听函数,上次变化的值,获取监听表达式的方法以及监听表达式,最后还包括是否需要使用深度对比(angular.equals())

53.js中继承实现的几种方式?

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

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

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

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

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

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

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

54.vue的生命周期?

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。 

每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。 

实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作 

挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取 

接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取 

接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情... 

当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿 

当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom 

当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等 

组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以 

55.说说c++,java,javascript这三种语言的区别?

从静态类型还是动态类型来看 

静态类型,编译的时候就能够知道每个变量的类型,编程的时候也需要给定类型,如Java中的整型int,浮点型float等。C、C++、Java都属于静态类型语言。 

动态类型,运行的时候才知道每个变量的类型,编程的时候无需显示指定类型,如JavaScript中的var、PHP中的$。JavaScript、Ruby、Python都属于动态类型语言。 

静态类型还是动态类型对语言的性能有很大影响。 

对于静态类型,在编译后会大量利用已知类型的优势,如int类型,占用4个字节,编译后的代码就可以用内存地址加偏移量的方法存取变量,而地址加偏移量的算法汇编很容易实现。 

对于动态类型,会当做字符串通通存下来,之后存取就用字符串匹配。 

从编译型还是解释型来看 

编译型语言,像C、C++,需要编译器编译成本地可执行程序后才能运行,由开发人员在编写完成后手动实施。用户只使用这些编译好的本地代码,这些本地代码由系统加载器执行,由操作系统的CPU直接执行,无需其他额外的虚拟机等。 

源代码=》抽象语法树=》中间表示=》本地代码 

解释性语言,像JavaScript、Python,开发语言写好后直接将代码交给用户,用户使用脚本解释器将脚本文件解释执行。对于脚本语言,没有开发人员的编译过程,当然,也不绝对。 

源代码=》抽象语法树=》解释器解释执行。 

对于JavaScript,随着Java虚拟机JIT技术的引入,工作方式也发生了改变。可以将抽象语法树转成中间表示(字节码),再转成本地代码,如JavaScriptCore,这样可以大大提高执行效率。也可以从抽象语法树直接转成本地代码,如V8 

Java语言,分为两个阶段。首先像C++语言一样,经过编译器编译。和C++的不同,C++编译生成本地代码,Java编译后,生成字节码,字节码与平台无关。第二阶段,由Java的运行环境也就是Java虚拟机运行字节码,使用解释器执行这些代码。一般情况下,Java虚拟机都引入了JIT技术,将字节码转换成本地代码来提高执行效率。 

注意,在上述情况中,编译器的编译过程没有时间要求,所以编译器可以做大量的代码优化措施。 

对于JavaScript与Java它们还有的不同: 

对于Java,Java语言将源代码编译成字节码,这个同执行阶段是分开的。也就是从源代码到抽象语法树到字节码这段时间的长短是无所谓的。 

对于JavaScript,这些都是在网页和JavaScript文件下载后同执行阶段一起在网页的加载和渲染过程中实施的,所以对于它们的处理时间有严格要求。

56.写个函数,可以转化下划线命名到驼峰命名?

public static String UnderlineToHump(String para){
StringBuilder result=new StringBuilder();
String a[]=para.split("_");
for(String s:a){
if(result.length()==0){
result.append(s.toLowerCase());
}else{
result.append(s.substring(0, 1).toUpperCase());
result.append(s.substring(1).toLowerCase());
}
}
return result.toString();
}
}

57.简单讲一讲ES6的一些新特性?

ES6在变量的声明和定义方面增加了let、const声明变量,有局部变量的概念,赋值中有比较吸引人的结构赋值,同时ES6对字符串、 数组、正则、对象、函数等拓展了一些方法,如字符串方面的模板字符串、函数方面的默认参数、对象方面属性的简洁表达方式,ES6也 引入了新的数据类型symbol,新的数据结构set和map,symbol可以通过typeof检测出来,为解决异步回调问题,引入了promise和 generator,还有最为吸引人了实现Class和模块,通过Class可以更好的面向对象编程,使用模块加载方便模块化编程,当然考虑到 浏览器兼容性,我们在实际开发中需要使用babel进行编译 

重要的特性: 

块级作用域:ES5只有全局作用域和函数作用域,块级作用域的好处是不再需要立即执行的函数表达式,循环体中的闭包不再有问题 

rest参数:用于获取函数的多余参数,这样就不需要使用arguments对象了, 

promise:一种异步编程的解决方案,比传统的解决方案回调函数和事件更合理强大 

模块化:其模块功能主要有两个命令构成,export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

58.call和apply用来做什么?

Call和apply的作用是一模一样的,只是传参的形式有区别而已 

1、改变this的指向 

2、借用别的对象的方法, 

3、调用函数,因为apply,call方法会使函数立即执行

59.js的数据类型?

字符串,数字,布尔,数组,null,Undefined,symbol,对象。

60.ajax返回的状态?

0 - (未初始化)还没有调用send()方法 

1 - (载入)已调用send()方法,正在发送请求 

2 - (载入完成)send()方法执行完成,已经接收到全部响应内容 

3 - (交互)正在解析响应内容 

4 - (完成)响应内容解析完成,可以在客户端调用了 

61.实现一个ajax?

AJAX创建异步对象XMLHttpRequest 

操作XMLHttpRequest 对象 

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

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

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

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

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

62.写出原生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);
}
}
}

63.知道PWA吗?

PWA全称Progressive Web App,即渐进式WEB应用。一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能

64.webpack和gulp区别?

gulp强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并、雪碧图、启动server、版本控制等),然后定义执行顺序,来让gulp执行这些task,从而构建项目的整个前端开发流程。 

webpack是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。

65.redux用处?

在组件化的应用中,会有着大量的组件层级关系,深嵌套的组件与浅层父组件进行数据交互,变得十分繁琐困难。而redux,站在一个服务级别的角度,可以毫无阻碍地将应用的状态传递到每一个层级的组件中。redux就相当于整个应用的管家。

66.redux里常用的方法?

提供 getState() 方法获取 state; 

提供 dispatch(action) 方法更新 state; 

通过 subscribe(listener) 注册监听器;

67.anjularjs和react的区别?

React对比Angular是思想上的转变,它也并不是一个库,是一种开发理念,组件化,分治的管理,数据与view的一体化。它只有一个中心,发出状态,渲染view,对于虚拟dom它并没有提高渲染页面的性能,它提供更多的是利用jsx便捷生成dom元素,利用组件概念进行分治管理页面每个部分(例如 header section footer slider)

68.vue双向绑定的原理?

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)。

69.说说vue,react,angularjs,jquery的区别?

JQuery与另外几者最大的区别是,JQuery是事件驱动,其他两者是数据驱动。 

JQuery业务逻辑和UI更改该混在一起, UI里面还参杂这交互逻辑,让本来混乱的逻辑更加混乱。 

Angular,vue是双向绑定,而React不是 

其他还有设计理念上的区别等

70.node的特性,适合处理什么场景?

Node.js借助事件驱动,非阻塞I/O模型变得轻量和高效,非常适合运行在分布式设备的数据密集型实时应用。

71.讲讲express?

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

72.promise的状态有哪些?

等待(pending)、已完成(fulfilled)、已拒绝(rejected)

73.介绍一下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 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

74.react单向数据流?

在React中,数据是单向流动的,是从上向下的方向,即从父组件到子组件的方向。 

state和props是其中重要的概念,如果顶层组件初始化props,那么React会向下遍历整颗组件树,重新渲染相关的子组件。其中state表示的是每个组件中内部的的状态,这些状态只在组件内部改变。
把组件看成是一个函数,那么他接受props作为参数,内部由state作为函数的内部参数,返回一个虚拟dom的实现。

75.react生命周期函数和react组件的生命周期?

React的组件在第一次挂在的时候首先获取父组件传递的props,接着获取初始的state值,接着经历挂载阶段的三个生命周期函数,也就是ComponentWillMount,render,ComponentDidMount,这三个函数分别代表组件将会挂载,组件渲染,组件挂载完毕三个阶段,在组件挂载完成后,组件的props和state的任意改变都会导致组建进入更新状态,在组件更新阶段,如果是props改变,则进入ComponentWillReceiveProps函数,接着进入ComponentShouldUpdate进行判断是否需要更新,如果是state改变则直接进入ComponentShouldUpdate判定,这个默认是true,当判定不需要更新的话,组件继续运行,需要更新的话则依次进入ComponentWillMount,render,ComponentDidMount三个函数,当组件卸载时,会首先进入生命周期函数ComponentWillUnmount,之后才进行卸载,如图

React的生命周期函数: 

初始化阶段:getDefaultProps获取实例的默认属性,getInitialState获取每个实例的初始化状态,ComponentWillMount:组件将被装载,渲染到页面上,render:组件在这里生成虚拟的DOM节点,ComponentDidMount:组件真正被装载之后 

运行中状态: componentWillReceiveProps:组件将要接收到属性的时候调用 shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。 componentWillUpdate:组件即将更新不能修改属性和状态 render:组件重新描绘 componentDidUpdate:组件已经更新 销毁阶段: componentWillUnmount:组件即将销毁

76.react和vue的原理,区别,亮点,作用?

我曾经看过vue作者尤雨溪的一个专访,他说过这样一段话(大概内容):做框架的时候我们也很纠结,到底是定制内容少一点好还是定制内容多一点好。定制少了,很多人不知道一些情况应该怎么处理,所以他就乱来,写的代码乱七八糟,性能也不好,然后他就会认为你的框架没做好,有的人还去网上喷你。但是当大家经验越来越丰富,反而希望受到框架的限制越少越好。因为随着经验的增加,大家都知道了各种场景下应该怎么处理,优化自己的代码。限制越少,自我发挥的空间就越大。 

最终我们可以看到,纠结之后,vue的选择居于react与angular之间,框架自身的语法比react多一点,但是又比angular少一点。 

也正是由于选择的不同,所呈现出来的写法与思考方式就一定会有所差异,不论优劣,但肯定会导致不同的偏好。 

react的简单在于,它的核心API其实非常少。所以我们会看到很多地方在说react其实是一个UI库,并不是一个完整的框架。他只是告诉我们如何创建组件以及组件之间如何进行数据传递。甚至于创建组件的方式正是使用ES6的class语法(createClass将会在react 16被丢弃)。 

因此开发中react的使用对于ES6的语法依赖非常高。因为react自身本来就没有多少强限制的语法。我们只需要掌握组件里的props,state,ref,生命周期,就好像没有过多额外的知识了。就连如果想要在jsx模板来遍历渲染,还得使用原生的map方法。而react的高阶组件,理解之后发现,其实就是JavaScript函数式编程中所涉及到的思维方式。 

所以在我看来,react的最大特点就是简单并且与原生JavaScript非常接近。即给开发者带来的束缚非常少。一个功能的实现,如果你知道使用原生JavaScript如何实现,那么你就一定能够很轻松的知道使用react如何实现。 

当然,核心API简单并不代表上手容易。在使用之初,如果你经验缺乏,那么你用react写出来的页面,性能可能会非常差。因为无意识的,你的组件可能会有非常多的多余的渲染。 

比如很多人在学习react的时候,会接触到一个倒计时的例子,这个例子使用修改组件中state的方式来实现。但是其实后来大家会慢慢知道,这种方式是非常错误的。因为state的每次修改,都会导致组件及其所有子组件的重新渲染。这是成本非常高的行为。当然,我还知道很多人,在调试react的时候,由于高频的重复渲染直接把浏览器都卡死的。这些问题都是尤雨溪所担心的限制过少带来的。 

网上有的自以为牛逼的人,用着react/vue这样的框架,其实写着很烂的代码,恐怖的是他们还嘲讽这嘲讽那的。还遇到过一个人,口口声声说自己用了angular好多年,说angular真的好垃圾啊,性能好差啊,什么什么的各种黑,结果连track by都不会用。而react由于没有真正意义上的双向绑定。因此在处理一些复杂场景会非常麻烦,比如复杂的表单验证。 

而相对而言,vue提供的能力则更多一点,这些便捷的能力会让初学者感觉到非常的幸福,因为很多效果只需要一些简单的代码既可以实现。我大概列举几条我个人认为非常棒的能力: 

统一管理的计算属性 

JavaScript的表达式非常便利,无论是vue还是react,表达式的能力是必不可少的。但正如vue官方文档所说,在模板中放入太多的逻辑会让模板过重且难以维护。而vue的组件中提供了一个计算属性来统一管理表达式。

<template>
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
</template>
<script>
export default {
name: 'example',
data () {
return {
message: 'Hello'
}
},
computed: {
reversedMessage: function() {
return this.message.split('').reverse().join('')
}
}
}
</script> 

class的动态语法让我感觉非常爽 

在实践中我们会发现非常多这样的场景,需要根据不同的状态来决定一个元素class的具体值。而如果仅仅只是简单的表达式或者条件判断在jsx模板中,例如下面这个样子就会让人感觉非常难受 

<p className={active ? 'note active' : 'note'}></p>

当稍微复杂一点的逻辑还这样处理就是难受到忍不了了。而vue中支持的语法则非常轻松的搞定了这个问题。 

// 可以放在任何你觉得舒服的位置

const pcls = {
active: active,
note: true
}
<p class={pcls}></p>

这样我们继续添加更多的class名也不会造成额外的复杂度了。 

当然,这仅仅只是一个工具方法就能搞定的问题,在使用react时,大家可以借助classnames来完成同样的功能。但vue是直接支持了。 

双向绑定 

由于react并不支持双向绑定,因此在复杂的表单验证时实现起来非常痛苦。而vue在以单向数据流为核心的同时,又没有完全抛弃双向绑定,这让在这样复杂的表单验证场景开发效率比react高出非常多。这也是vue省事儿的一个方面。 

修饰符 

我们在写事件处理逻辑时,常常需要e.preventDefault等操作。vue提供的修饰符功能可以帮助我们省去这些代码,极为方便。用多了就会发现,真TM好用。

<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联  -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>

当然,还有按键修饰符等,可以去官网进一步查看学习。 

vue提供的方便可爱的语法糖还有很多,就不细说,大家可以在官网上一一体验。正如文章开头所说,vue会有一些语法限制,而这些语法限制在某种程度上来说降低了我们的开发成本,提高了开发效率。这大概也就是很多人认为vue更加简单易学的原因所在吧。 

就从学习难易程度上来说,react之所以上手更加困难,主要的原因并不在于react本身,而在于围绕react的丰富的生态圈。正是由于react本身足够简单,所以我们需要掌握的react组件就更多。比如react-router,react-redux等。而且很多好用的,功能特别棒的组件在我们涉猎不广的时候都不知道。例如我在学习ant-design源码的时候,常常会惊讶于发现原来这里有一个组件可以这样用,真的好棒!而我在学习vue的时候又会惊讶的发现,原来这么棒的组件vue直接都已经支持了! 

所以后来我才发现,原来vue与react既然如此相似。 

我仍然更加偏好于react。但仅仅只是因为react的语法更加接近于ES6而已。

77.reactjs的组件交流?

React组件之间的交流方式可以分为以下三种 

1、父组件向子组件传值:主要是利用props来进行交流 

2、子组件向父组件传值:子组件通过控制自己的state然后告诉父组件的点击状态。然后在父组件中展示出来,如图: 

3、没有任何嵌套关系的组件之间传值:如果组件之间没有任何关系,组件嵌套层次比较深(个人认为 2 层以上已经算深了),或者你为了一些组件能够订阅、写入一些信号,不想让组件之间插入一个组件,让两个组件处于独立的关系。对于事件系统,这里有 2 个基本操作步骤:订阅(subscribe)/监听(listen)一个事件通知,并发送(send)/触发(trigger)/发布(publish)/发送(dispatch)一个事件通知那些想要的组件。 

78.有了解国react的虚拟DOM,虚拟DOM是怎么对比的呢?

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

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

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

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

79.react怎么获取真正的dom?

ReactDOM.findDOMNode()或this.refs

80.react的生命周期函数?

初始化 

1、getDefaultProps() 

设置默认的props,也可以用dufaultProps设置组件的默认属性. 

2、getInitialState() 

在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props 

3、componentWillMount() 

组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。 

4、 render() 

react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。 

5、componentDidMount() 

组件渲染之后调用,只调用一次。 

更新 

6、componentWillReceiveProps(nextProps) 

组件初始化时不调用,组件接受新的props时调用。 

7、shouldComponentUpdate(nextProps, nextState) 

react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候 

8、componentWillUpdata(nextProps, nextState) 

组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state 

9、render() 

组件渲染 

10、componentDidUpdate() 

组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。 

卸载 

11、componentWillUnmount() 

组件将要卸载时调用,一些事件监听和定时器需要在此时清除。

81.setState之后的流程?

在代码中调用setState函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。 经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个UI界面。 在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。 在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

82.react高阶组件?

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

83.说说自己理解的react?

React是用于构建用户界面的JavaScript库。React可以创建交互式UI。为应用程序中的每个状态建立的视图,并且React将在数据更改时进行更新,呈现正确的组件。另外,我们也可以构建管理自己状态的封装组件,然后将它们组合成复杂的UI。因为组件用JS编写而不是模板,所以可以通过应用传递数据,并使状态与DOM分离。

84.react的组件是通过什么去判断是否刷新的?

通过state是否改变

85.tcp建立连接的三次握手过程?

第一次握手:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN-SENT状态,等待Server确认; 

第二次握手:Server收到数据包后由标志位SYN=1得知Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN-RCVD状态,此时操作系统为该TCP连接分配TCP缓存和变量; 

第三次握手:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并且此时操作系统为该TCP连接分配TCP缓存和变量,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client和Server就可以开始传输数据。

86.CDN原理?

CDN的全称是Content Delivery Network,即内容分发网络。CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应。

87.请求方法head特性?

Head只请求页面的首部,head方法和get方法相同,只不过服务器响应时不会返回消息体,一个head请求的响应中,http头中包含的元信息应该和一个get请求的响应消息相同,这种方法可以用来获取请求中隐含的元信息,而不用传输实体本身,这个也经常用来测试超链接的有效性和可用性, 

Head请求有以下特点: 

只请求资源的首部, 

检查超链接的有效性 

检查网页是否被修改 

用于自动搜索机器人获取网页的标志信息,获取rss种子信息,或者传递安全认证信息等。

88.OSI七层模型?

应用层:文件传输,常用协议HTTP,snmp,FTP , 

表示层:数据格式化,代码转换,数据加密, 

会话层:建立,解除会话 

传输层:提供端对端的接口,tcp,udp 

网络层:为数据包选择路由,IP,icmp 

数据链路层:传输有地址的帧 

物理层:二进制的数据形式在物理媒体上传输数据

89.tcp和udp的区别,为什么三次握手,四次挥手?

TCP和UDP之间的区别 OSI 和TCP/IP 模型在传输层定义两种传输协议:TCP(或传输控制协议)和UDP(或用户数据报协议)。 UDP 与TCP 的主要区别在于UDP 不一定提供可靠的数据传输。 事实上,该协议不能保证数据准确无误地到达目的地。 

为什么TCP要进行四次挥手呢? 

因为是双方彼此都建立了连接,因此双方都要释放自己的连接,A向B发出一个释放连接请求,他要释放链接表明不再向B发送数据了,此时B收到了A发送的释放链接请求之后,给A发送一个确认,A不能再向B发送数据了,它处于FIN-WAIT-2的状态,但是此时B还可以向A进行数据的传送。此时B向A 发送一个断开连接的请求,A收到之后给B发送一个确认。此时B关闭连接。A也关闭连接。 

为什么要有TIME-WAIT这个状态呢,这是因为有可能最后一次确认丢失,如果B此时继续向A发送一个我要断开连接的请求等待A发送确认,但此时A已经关闭连接了,那么B永远也关不掉了,所以我们要有TIME-WAIT这个状态。 

当然TCP也并不是100%可靠的。

90.websocket和ajax的区别是什么?websocket的应用场景有哪些?

WebSocket的诞生本质上就是为了解决HTTP协议本身的单向性问题:请求必须由客户端向服务端发起,然后服务端进行响应。这个Request-Response的关系是无法改变的。对于一般的网页浏览和访问当然没问题,一旦我们需要服务端主动向客户端发送消息时就麻烦了,因为此前的TCP连接已经释放,根本找不到客户端在哪。 

为了能及时从服务器获取数据,程序员们煞费苦心研究出来的各种解决方案其实都是在HTTP框架下做的妥协,没法子,浏览器这东西只支持HTTP,我们有什么办法。所以大家要么定时去轮询,要么就靠长连接——客户端发起请求,服务端把这个连接攥在手里不回复,等有消息了再回,如果超时了客户端就再请求一次——其实大家也懂,这只是个减少了请求次数、实时性更好的轮询,本质没变。 

WebSocket就是从技术根本上解决这个问题的:看名字就知道,它借用了Web的端口和消息头来创建连接,后续的数据传输又和基于TCP的Socket几乎完全一样,但封装了好多原本在Socket开发时需要我们手动去做的功能。比如原生支持wss安全访问(跟https共用端口和证书)、创建连接时的校验、从数据帧中自动拆分消息包等等。 

换句话说,原本我们在浏览器里只能使用HTTP协议,现在有了Socket,还是个更好用的Socket。 

了解了WebSocket的背景和特性之后,就可以回答它能不能取代AJAX这个问题了: 

对于服务器与客户端的双向通信,WebSocket简直是不二之选。如果不是还有少数旧版浏览器尚在服役的话,所有的轮询、长连接等方式早就该废弃掉。那些整合多种双向推送消息方式的库(如http://Socket.IO、SignalR)当初最大的卖点就是兼容所有浏览器版本,自动识别旧版浏览器并采取不同的连接方式,现在也渐渐失去了优势——所有新版浏览器都兼容WebSocket,直接用原生的就行了。 

说句题外话,这点很像jQuery,在原生js难用时迅速崛起,当其他库和原生js都吸收了它的很多优势时,慢慢就不那么重要了。 

但是,很大一部分AJAX的使用场景仍然是传统的请求-响应形式,比如获取json数据、post表单之类。这些功能虽然靠WebSocket也能实现,但就像在原本传输数据流的TCP之上定义了基于请求的HTTP协议一样,我们也要在WebSocket之上重新定义一种新的协议,最少也要加个request id用来区分每次响应数据对应的请求吧。 

……但是,何苦一层叠一层地造个新轮子呢?直接使用AJAX不是更简单、更成熟吗? 

另外还有一种情况,也就是传输大文件、图片、媒体流的时候,最好还是老老实实用HTTP来传。如果一定要用WebSocket的话,至少也专门为这些数据专门开辟个新通道,而别去占用那条用于推送消息、对实时性要求很强的连接。否则会把串行的WebSocket彻底堵死的。 

所以说,WebSocket在用于双向传输、推送消息方面能够做到灵活、简便、高效,但在普通的Request-Response过程中并没有太大用武之地,比起普通的HTTP请求来反倒麻烦了许多,甚至更为低效。 

每项技术都有自身的优缺点,在适合它的地方能发挥出最大长处,而看到它的几个优点就不分场合地全方位推广的话,可能会适得其反。 

我们自己在开发能与手机通信的互联网机器人时就使用了WebSocket,效果很好。但并不是用它取代HTTP,而是取代了原先用于通信的基于TCP的Socket。 

优点是: 

原先在Socket连接后还要进行一些复杂的身份验证,同时要阻止未验证的连接发送控制指令。现在不需要了,在建立WebSocket连接的url里就能携带身份验证参数,验证不通过可以直接拒绝,不用设置状态; 

原先自己实现了一套类似SSL的非对称加密机制,现在完全不需要了,直接通过wss加密,还能顺便保证证书的可信性; 

原先要自己定义Socket数据格式,设置长度与标志,处理粘包、分包等问题,现在WebSocket收到的直接就是完整的数据包,完全不用自己处理; 

前端的nginx可以直接进行转发与负载均衡,部署简单多了

91.tcp/ip的网络模型?

TCP/IP模型是一系列网络协议的总称,这些协议的目的是使得计算机之间可以进行信息交换, 

TCP/IP模型四层架构从下到上分别是链路层,网络层,传输层,应用层 

链路层的作用是负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网,ADSL等, 

网络层负责分配地址和传送二进制数据,主要协议是IP协议, 

传输层负责传送文本数据,主要协议是TCP 

应用层负责传送各种最终形态的数据,是直接与用户信息打交道的层,主要协议是http,ftp等

92.知道什么是跨域方式吗,jsonp具体流程是什么,如何实现原声jsonp封装,优化,对于CORS,服务器怎么判断它该不该跨域呢?

常见的跨域方式大概有七种,大致可分为iframe、api跨域 

1、JSONP,全称为json with padding,解决老版本浏览器跨域数据访问问题,原理是web页面调用JS文件不受浏览器同源策略限制,所以通过script标签可以进行跨域请求,流程如下: 

首先前端设置好回调参数,并将其作为URL的参数 

服务器端收到请求后,通过该参数获取到回调函数名,并将数据放在参数中返回 

收到结果后因为是script标签,所以浏览器当做脚本运行, 

2、cors,全称是跨域资源共享,允许浏览器向跨源服务器发出XMLHTTP Request请求,从而克服了ajax只能同源使用的策略,实现cors的关键是服务器,只要服务器实现了cros接口,就可以跨域通信 

前端逻辑很简单,正常发起ajax请求即可,成功的关键在于服务器 Access-Control-Allow-Origin 是否包含请求页面的域名,如果不包含的话,浏览器将认为这是一次失败的异步请求,将会调用 xhr.onerror 中的函数。 

Cros使用简单,支持POST方式,但是存在兼容问题 

浏览器将cors请求分为两类,简单请求和非简单请求,对于简单请求,浏览器直接发出cors请求,就是在头信息之中增加一个origin字段,用于说明本次请求来自哪个协议+域名+端口,服务器根据这个值,决定是否同意本次请求,如果服务器同意本次请求,返回的响应中会多出几个头信息字段: 

Access-Control-Allow-Orign:返回origin的字段或者* 

Access-Control-Allow-Credentials,该字段可选,是一个bool值,表示是否允许发送cookie, 

Access-Control-Expose-Headers

3、服务器代理: 

即当你有跨域的请求操作时发给后端,让后端帮你代为请求, 

此外还有四中不常用的方式,也可了解下: 

location.hash: 

Window.name 

postMessage

93.怎么生成token,怎么传递?

接口特点汇总: 

1、因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效; 

2、因为是非开放性的,所以OAuth那套协议是行不通的,因为没有中间用户的授权过程; 

3、有点接口需要用户登录才能访问; 

4、有点接口不需要用户登录就可访问; 

针对以上特点,移动端与服务端的通信就需要2把钥匙,即2个token。 

第一个token是针对接口的(api_token); 

第二个token是针对用户的(user_token);

先说第一个token(api_token) 

它的职责是保持接口访问的隐蔽性和有效性,保证接口只能给自家人用,怎么做到?参考思路如下: 

现在的接口基本是mvc模式,URL基本是restful风格,URL大体格式如下: 

http://blog.snsgou.com/模块名/控制器名/方法名?参数名1=参数值1&参数名2=参数值2&参数名3=参数值3 

接口token生成规则参考如下: 

api_token = md5 ('模块名' + '控制器名' + '方法名' + '2017-07-18' + '加密密钥') = 770fed4ca2aabd20ae9a5dd774711de2 

其中的 

1、 '2013-12-18' 为当天时间, 

2、'加密密钥' 为私有的加密密钥,手机端需要在服务端注册一个“接口使用者”账号后,系统会分配一个账号及密码,数据表设计参考如下:

服务端接口校验,PHP实现流程如下: 

<?php 

1. 获取GET参数值 

$module = $_GET['mod']; 

$controller = $_GET['ctl']; 

$action = $_GET['act']; 

$client_id = $_GET['client_id']; 

$api_token = $_GET['api_token'];

2. 根据客户端传过来的client_id,查询数据库,获取对应的client_secret。 

$client_secret = getclientSecretById($client_id);

3. 服务器重新生成一份api_token 

$api_token_server = md5($module.$controller.$action.date('Y-m-d', time()).$client_secret);

4. 客户端传过来的api_token与服务器生成的api_token进行校对,如果不相等,则表示验证失败。 

if($api_token != $api_token_server){ 

exit('access deny'); 

5. 验证通过,返回数据到客户端。

再说第二个token(user_token),它的职责是保护用户的用户名及密码多次提交,以防密码泄露。 

如果接口需要用户登录,其访问流程如下: 

1、用户提交“用户名”和“密码”,实现登录(条件允许,这一步最好走https); 

2、登录成功后,服务端返回一个 user_token,生成规则参考如下: 

服务端用数据表维护user_token的状态,表设计如下: 

服务端生成user_token 后,返回给客户端(自己存储),客户端每次接口请求时,如果接口需要用户登录才能访问,则需要把 user_id 与 user_token 传回给服务端,服务端接受到这2个参数后,需要做以下几步:

1、检测 api_token的有效性; 

2、删除过期的 user_token 表记录; 

3、根据 user_id,user_token 获取表记录,如果表记录不存在,直接返回错误,如果记录存在,则进行下一步;

4、更新 user_token 的过期时间(延期,保证其有效期内连续操作不掉线); 

5、返回接口数据。 

那么token如何传递呢,ajax中传递token有以下几种方式: 

1、放在请求头中:

2、使用beforeSend方法设置请求头 

94.操作系统进程和线程的区别?

进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。 

线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。

95.线程的哪些资源共享,哪些资源不共享?

共享的资源有 

a. 堆  由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;因此new出来的都是共享的(16位平台上分全局堆和局部堆,局部堆是独享的) 

b. 全局变量 它是与具体某一函数无关的,所以也与特定线程无关;因此也是共享的 

c. 静态变量虽然对于局部变量来说,它在代码中是“放”在某一函数中的,但是其存放位置和全局变量一样,存于堆中开辟的.bss和.data段,是共享的 

d. 文件等公用资源  这个是共享的,使用这些公共资源的线程必须同步。Win32 提供了几种同步资源的方式,包括信号、临界区、事件和互斥体。 

独享的资源有 

a. 栈 栈是独享的 

b. 寄存器  这个可能会误解,因为电脑的寄存器是物理的,每个线程去取值难道不一样吗?其实线程里存放的是副本,包括程序计数器PC

96.操作系统里面的进程和线程的区别?

进程是具有一定独立功能的程序,他是系统进行资源分配调度的一个独立单位, 

线程是进程的一个实体,是cpu调度分派的基本单位,线程之间基本上不拥有系统资源 

一个程序至少有一个进程,一个进程至少有一个线程,资源分配给进程,同一个进程下所有线程共享该进程的资源

97.linux查询进程指令,查询端口,杀进程指令?

查询进程: 

ps 命令用于查看当前正在运行的进程。 

grep 是搜索 

例如: ps -ef | grep java 

表示查看所有进程里CMD是java的进程信息 

ps -aux | grep java 

-aux 显示所有状态 

ps 

杀死进程: 

kill -9[PID]

98.进程之间的通信方式有哪些?

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

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

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

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

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

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

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

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

99.redis和mysql的区别?

(1)类型上 

从类型上来说,mysql是关系型数据库,redis是缓存数据库 

(2)作用上 

mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢 

redis用于存储使用较为频繁的数据到缓存中,读取速度快 

(3)需求上 

mysql和redis因为需求的不同,一般都是配合使用。

100.B树的特性,B树和B+树的区别?

一个m 阶的B树满足以下条件: 

每个结点至多拥有m棵子树; 

根结点至少拥有两颗子树(存在子树的情况下); 

除了根结点以外,其余每个分支结点至少拥有m/2 棵子树; 

所有的叶结点都在同一层上; 

有k 棵子树的分支结点则存在 k-1 个关键码,关键码按照递增次序进行排列; 

关键字数量需要满足ceil(m/2)-1 <= n <= m-1; 

B树和B+树的区别: 

以一个m阶树为例。 

关键字的数量不同;B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的作用,但是B树虽然也有m个子结点,但是其只拥有m-1个关键字。 

存储的位置不同;B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据,但是B树的数据存储在每一个结点中,并不仅仅存储在叶子结点上。 

分支结点的构造不同;B+树的分支结点仅仅存储着关键字信息和儿子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息。 

查询不同;B树在找到具体的数值以后,则结束,而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。

101.尾递归?

如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。

102.如何写一个大数阶乘?递归的方法会出现什么问题?

function factorial(n){ 
return n > 1 ? n * factorial(n-1) : 1; 
} 

递归方法会有计算溢出的问题

103.把多维数组变成一位数组的方法?

法一:递归

function flatten(arr) {
var result = [];
for (var i = 0, len = arr.length; i < len; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]))
}
else {
result.push(arr[i])
}
}
return result;
}

 法二:toString

function flatten(arr) {
return arr.toString().split(',').map(function(item){
return +item
})
}

 法三:reduce

function flatten(arr) {
return arr.reduce(function(prev, next){
return prev.concat(Array.isArray(next) ? flatten(next) : next)
}, [])
}

 法四:rest运算符

function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}

 104.说一下冒泡和快排的原理?

冒泡排序:重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。 

快速排序:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

105.heap排序方法的原理,复杂度?

堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 

复杂度:O (nlgn)

106.几种常见的排序手法?

基本排序算法:冒泡,选择,插入,希尔,归并,快排

冒泡排序:

function bubbleSort(data){
var temp=0;
for(var i=data.length;i>0;i--){
for(var j=0;j<i-1;j++){
if(data[j]>data[j+1])
{
temp=data[j];
data[j]=data[j+1];
data[j+1]=temp;
}
}
}
return data;
}

 选择排序:

function selectionSort(data){
for(var i=0;i<data.length;i++){
var min=data[i];
var temp;
var index=1;
for(var j=i+1;j<data.length;j++){
if(data[j]<min)
{
temp=data[j];
data[j]=min;
min=temp;
}
}
temp=data[i];
data[i]=min;
data[index]=temp
}
}

 插入排序:

function insertSort(data){
var len=data.length;
for(var i=0;i<len;i++){
var key=data[i];
var j=i-1;
while(j>=0&&data[j]>key){
data[j+1]=data[i];
j--;
}
data[j+1]=key;
}
return data;
}

 希尔排序:

function shallSort(array) {
var increment = array.length;
var I
var temp; //暂存
do {
//设置增量
increment = Math.floor(increment / 3) + 1;
for (i = increment ; i < array.length; i++) {
if ( array[i] < array[i - increment]) {
temp = array[i];
for (var j = i - increment; j >= 0 && temp < array[j]; j -= increment) {
array[j + increment] = array[j];
}
array[j + increment] = temp;
}
}
}
while (increment > 1)
return array;
}

 归并排序:

function mergeSort ( array ) {
var len = array.length;
if( len < 2 ){
return array;
}
var middle = Math.floor(len / 2),
left = array.slice(0, middle),
right = array.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right)
{
var result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length)
result.push(left.shift());
while (right.length)
result.push(right.shift());
return result;
}

 快速排序:

function quickSort(arr){
if(arr.length==0)
return [];
var left=[];
var right=[];
var pivot=arr[0];
for(var i=0;i<arr.length;i++){
if(arr[i]<pivot){
left.push(arr[i]);
}
else{
right.push(arr[i]);
}
}
return quickSort(left).concat(pivot,quickSort(right));
}

107.设计模式?

单例模式:在它的核心结构中值包含一个被称为单例的特殊类。一个类只有一个实例,即一个类只有一个对象实例。 

工厂模式:在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 

发布订阅模式:在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接JS中常用的设计模式中,我最常用的是装饰者模式,在不改变元对象的基础上,对这个对象进行包装和拓展(包括添加属性和方法),从而使这个对象可以有更复杂的功能。收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

108.JS中常用的设计模式,我最常用的是装饰者模式,在不改变元对象的基础上,对这个对象进行包装和拓展(包括添加属性和方法),从而使这个对象可以有更复杂的功能。

109.一般通过什么方式学习前端?

自学,W3school等网站,阮一峰、冴羽等大神的博客,GitHub,掘金,segmentfault等交流平台,

 

posted @ 2019-08-12 15:10  IT-蓝童鞋  阅读(592)  评论(0编辑  收藏  举报