前言
本文是分为三大块分别是css、js、网络主要是略微讲解一下我面试中过程中的问到的一些面试题。第一次发文章未免有些紧张,想我在掘金社区白piao了半年多了(老脸一红),现在面试已经通过了,拿了几个小小的offer,相对比较悠闲,觉得是时候未社区做点力所能及的贡献了。假如感觉这篇小文章对你有所帮助,请给我点个赞呗(毕竟是第一次写,紧张)。假如有些问题说得不正确,还请各位掘友们在评论区斧正,感激不尽!
一、CSS相关
(一)盒子模型(box-model)
- 盒子模型分为两种,一种是标准的盒模型,另外一种是IE盒模型。
- 区别:盒模型的组成由内到外分别是content、padding、border、margin。标准盒模型的宽高只包括content;而IE盒模型的宽高则是由content、padding、border一起撑开。
- css中设置
标准盒模型:box-sizing: content-box
IE盒模型:box-sizing: border-box
(二)CSS选择器的优先级
| 选择器 | CSS权重 |
|---|---|
| !important | infinity |
| 行间样式 | 1000 |
| id选择器 | 100 |
| class选择器、属性选择器、伪类选择器 | 10 |
| 标签选择器、关系选择器、伪元素选择器 | 1 |
| 通配符选择器 | 0 |
注意:这些数值权重采用的是256进制,其中权重是可以叠加的。
(三)BFC、层叠上下文
- BFC的定义
BFC是块级格式上下文,它是一个独立的渲染区域,它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。 - 触发BFC的条件
- 根元素
- float的值不为none
- overfloat的值不为visible
- display的值为inline-block、flex、table-cell等
- position的值为absolute或者fixed
- BFC的约束条件
- 内部的Box会在垂直方向上一个接一个的放置
- 垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠(塌陷),与方向无关。)
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
- BFC的区域不会与float的元素区域重叠
- 计算BFC的高度时,浮动子元素也参与计算
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然。
- 层叠上下文 层叠上下文是一个三维上的概念,简单来说若一个元素含有层叠上下文,那么这个元素在Z轴上就“高人一等”,最终表现就是离观察者越近。
- 怎么产生层叠上下文。
- HTML中的根元素本身j就具有层叠上下文,称为“根层叠上下文”。
- 普通元素设置position属性为非static值并设置z-index属性为具体数值,产生层叠上下文。
- CSS3中的新属性也可以产生层叠上下文。
- 层叠等级
- 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在Z轴上的上下顺序。
- 在其他普通元素中,它描述定义的是这些普通元素在Z轴上的上下顺序。
结论:普通元素的层叠等级优先由其所在的层叠上下文决定,层叠等级的比较只有在当前层叠上下文元素中才有意义。不同层叠上下文中比较层叠等级是没有意义的。
(四)主流浏览器以及其内核
| 主流浏览器 | 内核 |
|---|---|
| Webkit | |
| IE | Trident |
| Safari | webkit |
| Firefox | Gecko |
| Opera | Presto |
二、js相关
(一)Nodejs和浏览器js的区别
- 浏览器中的js
遵循ES的语法规范,添加了DOM(文档对象模型)和BOM(浏览器对象模型) - Nodejs
遵循ES的语法规范,因为这是在服务器端操作来实现操作服务器端的script,所以它没有DOM,它增加了核心API,使用频繁的API被内置到node环境中,并且它也可以引进第三方的API。
(二)js读写cookie
- 读cookie
console.log(document.cookie) - 写cookie
document.cookie = 'username=zhangsan;password=123;'
注意:假如服务端设置了httpOnly,那么可以防止客户端读取cookie,可以在一定程度上预防xss攻击。在服务端设置httpOnly样例
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly;expires=${getCookieExpires()}`)
(三)常见的类数组对象
arguments、NodeList(节点对象)、String构造出来的实例对象;顺便提一下常见的类数组的转数组的一些方式,以arguments为例
- 用点运算符展开(写法优雅)
[...arguments] - 用slice方法(性能推荐)
Array.prototype.slice.call(arguments) - 用splice方法
Array.prototype.splice.call(arguments, 0)
(四)如何做一个AJAX Request?
const xhr = new XMLHttPRequest();
xhr.open('POST', 'http://www.baidu.com', true); // method、url、async
xhr.send('username=zhangsan&password=123');
其中XMLHttpRequest中有readyState和onreadystatechange
-
readyState中有五个状态
state name description 0 Uninitialized XMLHttpRequest 对象已建立,但未初始化(未调用open方法) 1 open 初始化,open方法已经调用,但是请求还没有被发送 2 sent 请求已经发送(send方法已经调用) 3 receiving 所有响应头部都已经接收到。响应体开始接收但未完成。 4 loaded 数据接收完毕, 此时可以通过responseBody和responseText获取完整的响应数据 -
onreadystatechange事件回调方法在readystate状态改变时触发
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) { // 响应数据接收完毕
const status = xhr.status; // 获取服务器响应的状态码
if(status === 200) {
let res = xhr.responseText;
// todo...
}
}
}
(五)模块化之AMD、CMD、Commonjs、ES6 module
- commonJS用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。
- AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
- CMD是另一种js模块化方案,它与AMD很类似,不同点在于:AMD推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。
- CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。CommonJS模块是运行时加载,ES6模块是编译时输出接口。
- exports和module.exports的区别:require导出的内容是module.exports的指向的内存块内容,并不是exports的。区分他们之间的区别就是exports只是module.exports的引用,辅助后者添加内容用的。用内存指向的方式更好理解。
(六)Promise.all()和Promise.race()的区别
let allP = Promise.all([p1, p2, p3]);
let raceP = Promise.race([p1, p2, p3]);
- 他们都是将多个promise实例包装成一个promise实例
- 但是Promise.all()中只要有一个的状态返回rejected,那么promise实例就会变成rejected,假如想要allP是resolved状态,那么p1,p2,p3必须都返回resolved才可以。
- 而Promise.race()只要p1、p2、p3之中有一个实例率先改变状态,raceP的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给raceP的回调函数。Promise.race()的应用场景例如超时通知用户。
// 超时通知用户,超过5s假如没接收到响应就返回request timeout
const p = Promise.race([
fetch('/test'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
(七)执行上下文
执行上下文的生命周期分为两个:
- 创建阶段
创建阶段主要做的工作就是创建变量对象、建立作用域链、确定this指向。其中创建变量对象可分为四部曲:
- 创建变量对象即VO(VariableObject,初始时是一个空对象)。
- 添加arguments属性,并赋值。找出当前函数执行环境下的被var定义的变量或者形参,并赋值为undefined。
- 将形参和实参进行统一。
- 找出当前执行环境下的函数定义的函数名作为VO的属性,属性值就为定义的函数(假如出现与变量相同的属性名会覆盖掉,即函数提升的优先级更高)。
- 执行阶段 将执行到的函数环境下的VO转化为AO(Activation Object活动对象),然后同步执行每条语句,需要赋值的话就更新AO对象。
注意:上面讲的是函数的执行上下文的创建和执行,全局的执行上下文跟上面的步骤是一样的,但是它的变量对象是window。
三、网络相关
(一)HTTP1.0、HTTP1.1、SPDY、HTTP2.0、HTTP3.0
-
HTTP1.1跟HTTP1.0的区别主要体现在 +缓存处理(增加了if-match、cache-control、if-none-match、etag等)
- 带宽优化(请求头引入range,支持只请求资源的某一部分)
- host处理(请求头部信息必须带上host,因为一个ip地址可能对应多个主机)
- 长连接(connection: keep-alive)
- 错误通知管理(增加了24个错误状态码响应码)。
-
HTTPS和HTTP的区别
- HTTPS需要到CA申请证书
- HTTP协议是运行在TCP之上,HTTPS协议是运行在SSL/TLS之上,SSL/TLS是运行在TCP之上。
- HTTP传输的内容都是明文,HTTPS传输的内容都是经过加密的。
- HTTP的默认端口为80,HTTPS的默认端口为443。
-
SPDY与HTTP1.*的区别
- SPDY是基于HTTPS协议进行加密传输的;
- 降低延迟(采用多路复用的方法);
- 可以设置请求优先级(为了解决多路复用带来的问题);
- 进行header压缩;
- 服务端推送。
-
HTTP2.0跟SPDY的区别 HTTP2.0是基于SPDY进行改进的,不过还是有一些区别
- HTTP2.0支持明文传输,SPDY强制使用HTTPS。
- HTTP2.0采用的消息头压缩算法是HPACK,SPDY采用的压缩算法是DEFLATE。
-
HTTP2.0跟HTTP1.*的区别(跟SPDY跟HTTP1.*的区别有点接近)
新的二进制格式(因为http1.*是基于文本进行解析的,而http2.0是基于二进制格式进行解析的)、多路复用、header压缩、服务端推送。 -
HTTP3.0 HTTP3.0是基于QUIC协议,而QUIC协议是基于UDP协议的,不过QUIC协议在这上面增加了一些功能例如多路复用、0-RTT(往返时延)、纠错机制、使用TLS1.3加密、流量控制、有序交付、重传等。
(二)TCP三次握手和四次挥手
- TCP三次握手
- 第一次握手:客户端向服务端发送带有SYN标记位的连接请求报文段,客户端进入SYN_SENT状态。
- 第二次握手:服务端接收到来自客户端的请求连接的报文后,如果同意连接,则向客户端发送带有SYN和ACK标记位的应答报文,发送之后服务端进入了SYN_RECEIVED状态。
- 第三次握手:当客户端接收到服务器端同意建立连接的报文后,客户端再向服务器端发送带有ACK标记的确认建立连接的报文段,随后客户端进入了ESTABLISHED状态,当服务端收到这个应答后也进入ESTABLISHED 状态,此时连接建立成功。
- TCP四次挥手
- 第一次挥手:客户端向服务端发送带有FIN标记的请求释放连接的报文段,此时客户端进入了FIN_WAIT1(终止等待1)状态。
- 第二次挥手:服务器端接收到客户端的请求释放连接的报文段时,会告诉应用层要释放TCP连接了。然后会向客户端发送带有ACK的报文,随后服务端进入了CLOSE_WAIT状态,客户端接收到来自服务器端的应答后会进入FIN_WAIT2(终止等待2)。此时不会再接收来自客户端的数据,但是服务端还可以发送数据给客户端。
- 第三次挥手:若此时还有数据没发送给客户端,那么会继续发送,发送完毕后会向客户端发送带有FIN标记的请求释放连接的报文,然后服务端进入到LAST_ACK状态。
- 第四次挥手:客户端收到服务端的请求释放连接的请求后,会向服务器发送带有ACK标记的确认应答报文,此时客户端进入到TIME_WAIT状态,该状态会持续2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入CLOSED状态。
结语
你的一个认可,将是我不断前进的动力。同时我也祝福大家能找到自己满意的工作,激流勇进,丝毫不殆。最后还祝掘友们,国庆节快乐!!!