这里结合了CSDN多位博主和自己当时被问到的的深信服面试题,为了锻炼自己的答题能力和技术点理解,这里对博主的各个题目进行了自己的解答(最好用自己的理解自己的话解答),部分解答借鉴了博主的回答,同时对部分问题进行了相关拓展延伸。记在word笔记的时候没有记录博主地址,但还是感谢分享,一起努力加油啊!
核心:宽高设置为0,由边框来控制大小,然后边框颜色改为透明,然后更改一遍的边框颜色为自己想要的颜色
div{
width: 0;
height: 0;
border:50px solid transparent;
border-bottom-color:red;
}
注意:上面这样设计的话,div的实际占位还是个方形,如下代码实现实际占位变为三角形
div{
width: 0;
height: 0;
border-left:20px solid transparent;
border-right:20px solid transparent;
border-bottom-color:20px solid red;
}
(1)事件流
HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。
什么是事件流:从页面中接收事件的顺序
addEventListener:addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
IE只支持事件冒泡。
(2)如何让事件先冒泡后捕获
在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获事件。
(3)事件委托
简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
好处:比较适合动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。
1)遍历属性法
一旦该对象的属性是可遍历的即说明该对象存在属性,则返回false,否则该对象为空对象。
function judgeObj(obj){
for(var attr in obj){
return false
}
return true
}
console.log(judgeObj({}))
(2)JSON.stringify() 方法
function judgeObj2(obj){
if(JSON.stringify(obj) == '{}')
return true
else
return false
}
console.log(judgeObj2({}))
(3)ES6 Object.keys()方法
Object.keys方法是JavaScript中用于遍历对象属性的一个方法 。
它传入的参数是一个对象,返回的是一个数组,数组中包含的是该对象所有的属性名。
function judgeObj3(obj) {
if(Object.keys(obj).length == 0){
return true
} else {
return false
}
}
for (var key in arr){
console.log(arr[key]);
}
for (var value of arr){
console.log(value);
}
若要用 for of 遍历对象,要结合Object.keys()进行使用:
for(var key of Object.keys(arr)){
//使用Object.keys()方法获取对象key的数组
console.log(arr[key]);
}
一次完整的HTTP请求过程 版本 1.0
HTTP请求过程--复习推演
1、url(www.baidu.com)=> ip (192.168.1.2)
2、拿到ip,与服务器建立TCP连接
3、TCP连接后,发送HTTP请求 (TCP是比http更底层的协议,ip是tcp下面一层)
4、HTTP连接后,服务器把html发给浏览器
5、浏览器解析html(js、css、图片 下载 运行)
6、浏览器渲染html
7、服务器关闭连接(TCP HTTP)
注:
(1)DNS怎么找到域名的?
DNS域名解析采用的是递归查询的方式
过程:先去找DNS缓存->缓存找不到就去找根域名服务器->根域名又会去找下一级,这样递归查找之后,找到了,给我们的web浏览器
过程(面试):浏览器自身域名缓存区找 =》操作系统的域名缓存区找 =》hosts文件找 =》域名服务器找
(2)为什么HTTP协议要基于TCP来实现?
TCP是一个端到端的可靠的面相连接的协议,HTTP基于传输层TCP协议,不用担心数据传输的各种问题(当发生错误时,会重传)
(3)最后一步浏览器是如何对页面进行渲染的?
(4)TCP的三次握手和四次挥手
三次握手:
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,等待服务器确认
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手
四次挥手:
第一次挥手:客户端进程发出连接释放报文(FIN报文),并且停止发送数据
第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v
第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1
第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。
(1)概念
(2)注意点
(3)补充
触发重排的条件:任何页面布局或几何属性的改变都会触发重排
(4)扩展
重绘重排会造成耗时、浏览器卡顿,那么如何做优化呢?(尽量减少DOM操作)
1、浏览器优化:浏览器会把引起回流、重绘的操作放入一个队列,等队列中的操作到了一定数量或者时间间隔,就flush这个队列进行一个批处理。这样就可以让多次回流重绘变成一次。
2、代码优化:减少对渲染树的操作,可以合并多次DOM和样式的修改,并减少对style样式的请求。
Web storage(HTML5) | ||||
cookie | session | sessionstorage | localstorage | |
数据生命周期 | 一般由服务器生成,在设置失效时间(expires)内有效(与窗口或浏览器是否关闭无关)。若在浏览器设置,默认浏览器关闭后失效 | 除非被清除,否则永久保存(刷新页面数据依旧存在) | 仅在当前会话有效,关闭窗口或浏览器后清除 | 除非web应用主动删除,否则永不失效 |
存放数据大小 | 4k左右 | 5M | 5M | |
与服务端通信 | 保存在浏览器端。每次都会携带在HTTP请求头中,保存过多数据会有性能问题 | 保存在服务器端,不参与服务器通信 | 保存在客户端,不参与服务器通信 | |
安全性 | 安全性较低(cookie诈骗cookie截取) | session安全性大于cookie | ||
易用性 | 一般接口需要自己封装 | 接口可以直接使用 | ||
作用域 | 在浏览器所有的同源窗口中共享 | 不能在不同的浏览器窗口共享 | 不能在不同的浏览器窗口共享,在同源窗口中可以共享 | |
使用场景 | 主要用于保存登录信息 1、判断用户是否登录过网站,方便下次登录实现自动登录或记住密码 2、上次登录的时间等信息 3、上次查看的页面 4、浏览计数 |
用于保存每个用户的专用信息,变量的值保存在服务器端,通过sessionID来区分不同用户。 1、购物车 2、用户登录信息 3、将某些数据放入session中,供同一用户的不同页面使用 4、防止用户非法登录 |
敏感账号一次性登录、表单,对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便 | 常用于长期登录(判断用户是否登录),适合长期保存在本地的数据。 购物车信息、HTML5游戏产生的一些本地数据 |
优点 | 1、存储空间大 2、节省网络流量 3、可在本地直接获取,不需要与服务器交互 4、获取速度快 5、安全性较高 6、更多丰富易用的API接口 7、支持事件通知机制,可以将数据更新的通知发送给监听者 8、操作方法:setItem、getItem、removeItem、clear、key、length |
|||
缺点 | 1、大小受限 2、用户可以禁用cookie,使功能受限 3、安全性较低 4、有些状态不能保存在客户端 5、同源请求时会被携带(服务端和客户端互传,不论是否需要),加大http流量,数据过多影响性能 6、cookie数据有路径(path)的概念,可以限制cookie只属于某个路径下 |
get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。
状态码:状态码用于表示服务器对请求的处理结果
列举几种常见的:
面试:性能提升 =》减少HTTP请求 =》HTTP缓存控制(浏览器缓存)?
回答:
补充问题:
1、为什么有 expires 还要 cache-control
因为expires有服务器和浏览器时间不同步问题,expires是绝对时间,cache-control是相对时间
2、为什么有 last-modify 还要 etag
因为 last-modify 有精度问题 到秒,etag 没有精度问题,只要资源改变,etag值就会改变
详细理解:
(1)浏览器缓存机制
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
(2)浏览器缓存策略
缓存策略都是通过设置 HTTP Header 来实现的,根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强缓存和协商缓存。
1、浏览器加载一个页面的简单流程如下:
浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。(强缓存)
如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。(协商缓存)
如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。(新的请求)
2、强缓存:不会向服务器发送请求,直接从缓存中读取资源
强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control
强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容,那我们如何获知服务器端内容是否已经发生了更新呢?此时我们需要用到协商缓存策略。
3、协商缓存:强制缓存未命中,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。主要有以下两种情况:
协商缓存--协商个啥呢?
浏览器问服务器,我缓存的文件有没有更新啊?
- 没有更新:浏览器可以用缓存 304
- 更新了:浏览器不能用缓存,服务器发新的给浏览器 200
协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag (帮助浏览器跟服务器进行协商)
4、HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
5、缓存机制:强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
6、如果什么缓存策略都没设置,那么浏览器会怎么处理?
对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
(3)实际应用场景
(4)用户行为对浏览器缓存的影响
新开窗口 | 有效 | 有效 |
---|---|---|
用户操作 | Expires/Cache-Control | Last-Modified/Etag |
地址栏回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
前进、后退 | 有效 | 有效 |
F5 刷新 | 无效 | 有效 |
Ctrl+F5 刷新 | 无效 | 无效 |
HTTP1.0 中定义的方法:
HTTP1.1 中新增的5种方法:
URL和URN 都属于 URI,为了方便就把URL和URI暂时都通指一个东西
74256831
var merge = function(nums1, m, nums2, n) {
let nums = []
let i = 0
let j = 0
while(i < m && j < n){
if(nums1[i] <= nums2[j]){
nums.push(nums1[i++])
} else {
nums.push(nums2[j++])
}
}
while(i < m){
nums.push(nums1[i++])
}
while(j < n){
nums.push(nums2[j++])
}
return nums
};
持续解答更新中。。。。。。