之前总结过好多的面试题,但是笔记都是都是零零散散的,为了方便,以后都汇总在这里啦~都是自己遇到过的(可能会存在重复哦),不定时更新~~
HTML CSS
1.隐藏元素有哪几种方法?
1.直接对该元素使用:display:none.(元素不存在)
2.对该元素的父级使用:display:none.(子元素不存在)
3.对该元素使用:visibility:hidden.(元素存在)
(对父元素使用visibility:hidden,子元素存在,可使用visible:visible显示元素)
4.设置透明:opacity:0;
5.设置元素宽高均为0;
2.如何让其子元素不受父元素及祖宗元素样式的影响,成为一个独立容器?
contain: 隔离指定内容的样式/布局和渲染,包含七个属性值:
none 无
layout 开启布局限制
style 开启样式限制
paint 开启渲染限制
size 开启size限制
content 开启除了size外的所有限制
strict 开启 layout, style 和 paint 三种限制组合
" 开发人员可以用这个 contain 属性声明一个元素和它的子元素是——尽可能的——和页面上的其它元素保持独立 " --- 来自w3c规范
3.简述一下从输入一个url到渲染出一个页面的过程,浏览器做了些什么?
1. 首先是输入一个URL并回车,浏览器去查看该URL是否存在缓存
2. 通过DNS去解析域名获取到IP地址。
3. 接下来用该IP地址去与服务器建立TCP连接(三次握手)
4. 成功之后向服务器发起请求,服务器响应请求,渲染页面。
5. 接下来关键路径渲染(CRP):dom树-----cssOM树------ render树----重排-----重绘
(注:重排一定引起重绘,重绘不一定引起重排)
总体来说关键路径渲染分为六步:
1.创建DOM树----------从根元素开始,对应的创造节点,其中包含元素的所有属性
注意:浏览器并不需要等待整个html解析完才开始显示页面。但是可能存在其他资源阻碍页面渲染,比如css 和 js。
2.创建CSSOM树--------对DOM元素的样式进行渲染,其中包括有些继承的或者新增的样式。
注意:由于css会存在继承 覆盖等因素,所以必须是全部解析完才能进入下一步的。也就是css一直渲染不完,后面的一直会不执行。
3.执行js脚本-------当页面解析到script标签的时候,无论是内联还是外联,浏览器就会暂停页面的解析,转而解析js。
(这也是为什么js引用文档中的元素时,要放在元素后面了)
4.生成渲染树 ------- 最终能呈现到页面上的树形结构,其中不包含css的隐藏属性。
5.生成布局 ------ 生成页面的一个架构(横向布局或者纵向布局)
6.渲染页面 -------- 所花费时间取决于DOM的大小以及css的复杂性。
完成之后关闭TCP连接(四次挥手)
4.如何把DOM转化为图片?
使用svg中的<foreignobject>,foreignobject 标签内可以嵌套任何html标签,SVG元素允许包含不同的XML命名空间,利用XMLSerializer,实例化XMLSerializer并调用其serializaToString()方法把一个XML文档或者Node对象转为未解析的XML标记的一个字符串
简单描述为:将DOM转化成xhtml,再把图片转为svg格式,使用foreignobject编译成可解析的字符串。
5.MVC && MVVM
MVC(modal-view-controller):
1.视图被用户看到---视图 即给用户展示的页面
2.用户使用控制器输入操作 --- 控制器:翻译用户的输入,并按照用户的输入去操作模型
3.控制器操作模型
4.模型更新视图 ---- 模型:管理应用的行为和数据,响应数据请求(来自页面)和更新页面状态(来自控制器)
视图层跟控制器层 依赖于模型层。
MVP是MVC的一种变种,(model-view-presenter),该模式下所有从视图发出的事件,都会通过代理给松散控制器进行处理;同时,控制器也通过视图暴露的接口与其进行通信。
MVVM(model-view-modelView):view不部署任何业务逻辑,只是把数据操作传达给viewModel,然后被动等着更新就行了。viewModel与model层双向数据绑定,也就是前者把行为和操作传给后者,后者把更改的状态和数据返给前者,由前者来处理view的业务逻辑然后通知view去更新页面。view与viewmodel层不发生任何联系
6.移动端适配
Flexible方案:借助js 控制 viewport的能力,使用rem模拟vw。rem是相对于html的font-size来做计算的计算属性,通过设置document.fontsize来统一整个页面的布局标准。可以使用postCSS-----(一般设置的是100份,即100px=1rem的换算 方便计算)
px:绝对长度单位,是针对显示器屏幕分辨率大小来说的
rem:相对长度单位,相对与当前文本对象的字体大小(html的fontsize)来说的
em:非固定值,所有大小相对于父元素的大小决定的
7.css怎么计算CSS优先级?
8.position属性值?
static 默认值
relative 相对定位
absolute 绝对定位
fixed 固定定位
sticky fix+relative
9.如何清除浮动?
1. 给父元素设置高度
2. 使用伪类after,设置content:"",设置clear,
3. 在父元素后面加个空的div并隐藏
4. 给父元素添加 overflow:hidden
float_div:after{
content:".";
clear:both;
display:block;
height:0;
overflow:hidden;
visibility:hidden;
}
10.盒模型
border-box: 宽度 = content + padding + border ;
content-box: 宽度 = content
设置属性: border-sizing : content-box / border-box;
默认值是content-box, 常用的是content-box;
11.什么是BFC 怎么形成一个BFC?
block format context(块级格式化上下文)
形成BFC:
1.overflow:不为visible;
2.display的值为:flex,table-cell,inline-block,inline-flex
3.根元素
4.position为absolute或者fixed
5.float不为none。
12.怎么画一个三角形?
13.怎么实现
JS
1.ES6中的var let const 有什么区别?
共同点:都是用于声明变量 常量。
var:用var声明的变量存在变量提升,挂载于window上。
let:使用let声明的变量一开始就会形成一个封闭作用域,作用范围只存在于let存在的代码段,外部不能使用。如果在使用let声明变量前使用了该变量,就会形成暂时性死区(TDZ)
const;声明的变量,既不存在变量提升也不能被修改,如果是复合类型,可修改其属性
同一作用域下,let和const不可以声明同名变量。var可以(后面的覆盖前面的)
2.如何解析queryString?(queryString的解码和编码)
encodeQueryString
decodeQueryString
3.什么是原型 原型链?
4.创建实例时,new关键字做了什么或者说有什么作用?
class Fruit {
constructor(apple,banana){
this.appleName = apple;
this.bananaName = banana;
// 可以利用 new.target写出不能被独立使用,只有被继承才能使用的类
console.log(new.target); // 返回new命令作用于的那个构造函数,一般用在constructor中
}
name() {
console.log("my name is " + this.bananaName + this.appleName)
}
}
const myFruit = new Fruit();
作用:
1、创建一个新的对象,这个对象的类型是object;
2、查找class的prototype上的所有方法、属性,复制一份给创建的Object
3、将构造函数class Fruit内部的this指向创建的Object
4、创建的Object的__proto__指向class的prototype
5、执行构造函数class
6、返回新创建的对象给变量b
总结:new关键字以构造函数为模板创建一个新的对象,该对象复制了构造器中的所有成员变量,同时this指向新创建的对象。
注意:如果不使用new关键字,直接调用构造函数创建实例,this指向的是window
5.实现数组的去重有哪几种方式?
const arrs = [1,2,3,4,1,3,5,5,6,1,2,9];
// 1.使用indexOf:返回在数组中找到一个给定元素的第一个索引,否则返回-1 (不会改变原有数组)
function unique1(arr){
if(!Array.isArray(arr))return;
var newArr = []; // 创建新数组接收不同值
for(var i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i]) === -1) { // 在新数组中查找有没有arrs中的值,没有就把当前值push进新数组,有则不做任何操作,进入下一次循环
newArr.push(arr[i])
}
}
return newArr;
}
console.log(unique1(arrs)) // [1, 2, 3, 4, 5, 6, 9] 字符串数组和数字都可以用,特殊字符不行
// 2.sort:数组排序(升序或降序) 只能用于数字
function unique2(arr) {
if(!Array.isArray(arr))return;
let sortArr = arr.sort((a,b)=>a-b); // 升序
let newArr = [];
for(let i=0;i<sortArr.length;i++) {
// 相邻元素比较
if(arr[i] != arr[i+1]) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique2(arrs)) // [1, 2, 3, 4, 5, 6, 9]
// 3.splice(开始位置,删除几个元素,添加哪些元素):删除或替换现有元素或者原地添加新的元素来修改数组,返回被删除的元素组成的一个数组。此方法会改变原数组
function unique3(arr) {
if(!Array.isArray(arr))return;
// 循环元素
for(let i=0;i<arr.length;i++) {
// 循环比较值 删除重复元素 i=0 i=1 i=2
for(let j = i+1;j<arr.length;) { // j =1 j=2
if(arr[i] === arr[j]) {
arr.splice(j,1); // arr = [1,1,2]
} else {
j++ //j=3
}
}
}
return arr
}
console.log(unique3(arrs)) // [1, 2, 3, 4, 5, 6, 9]
// 4.includes: 数组是否包含某个具体值
function unique4(arr) {
if(!Array.isArray(arr))return;
let newArr = [];
for(let i=0;i<arr.length;i++) {
if(!newArr.includes(arr[i])) {
newArr.push(arr[i])
}
}
return newArr
}
console.log((unique4(arrs))) // [1, 2, 3, 4, 5, 6, 9]
// 5.set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用
function unique5(arr) {
// 使用构造器将Array转为Set对象
let newArr = new Set(arr);
return [...newArr] // 使用...操作符将Set转换Array
}
console.log(unique5(arrs)) // [1, 2, 3, 4, 5, 6, 9]
6.new操作符做了哪些事?
1. new操作符创建一个空对象,
2. 把这个对象原型指向构造函数的prototype,
3. 执行构造函数以后返回值这个对象。
也就是 使用new创建对象实例。
7.闭包
闭包就是能够读取其他函数内部变量的函数,或者 子函数在外调用, 子函数所在的父函数的作用域不会被释放。简单来说就是函数里面返回一个函数。
过多使用闭包会引起内存泄漏,由于闭包会使得函数中的变量都被保存在内存中,无法释放从而造成内存泄漏。解决办法是:在退出之前将不使用的局部变量指向null。
使用场景:给页面上多个DOM循环绑定事件的时候
for(var i = 0; i< btns.length; i += 1){
( function(i) {
btns[i].inclick = function() {
alert(i)
}
})(i)
}
8.说一说事件冒泡,阻止事件冒泡的办法?
事件冒泡是指:事件会从最内层的元素开始发生,一直向上传播,直到document对象。
方法:1.给子级加event.stopPropagation(); ---- 只阻止了冒泡事件
2.在事件处理函数中返回false; ----既阻止了冒泡事件,又阻止了默认事件
3.event.target = event.currentTartget,让触发的元素等于绑定事件的元素,也可以阻止事件冒泡
事件捕获:事件会从最外层开始发生,然后再到具体的元素。
先捕获再冒泡
事件委托:利用事件冒泡,只指定一个事件处理程序,可以管理某一类型的事件。
addEventListner:第三个参数接收一个对象,其值有:
capture --- 捕获 (为false,即为事件冒泡,为true,即事件捕获)
once --- 只监听一次
signal --- 移除监听器
passive --- 是否调用event.preventDefault.(true则永远不调用)
阻止默认事件:1.event.preventDefault( );2. return false;
10.数组map跟reduce的区别?
map()是将传入的函数依次作用到序列的每个元素,每个元素都是独自被函数“作用”一次;
reduce()是将传人的函数作用在序列的第一个元素得到结果后,把这个结果继续与下一个元素作用(累积计算)
map()返回的是个集合,函数依次作用到每一个元素之后的新数组集合。
reduce()返回的是函数经过执行运算后的结果
11.forEach跟map的区别?
forEach 只是对数组进行循环,对数组进行相关操作,没有返回值,会改变原数组;
map是可传入函数对数组的每一项进行作用并返回一个新的数组,不会改变原数组。
12.js处理错误
js错误分两种:
一种是程序逻辑不对,导致代码运行报错
一种是执行过程中,程序可能遇到无法预测的异常情况而报错,如:网络链接中断,没有操作权限等。
js使用try...catch...finally 来处理js错误。
当代码块被try包裹的时候表示该代码可能会出现异常,若出现异常,则不再继续执行后续代码,进入到catch里面。catch中接收一个变量e表示接收到的错误。最后无论有没有错误都会执行finally里面的代码。
js存在6种错误类型:
1.SyntaxError:语法错误
2.Uncaught ReferenceError:引用错误。引用一个不存在的变量是报的错
3.RangeError:范围错误。超出作用范围的错误,如数组长度为负数,方法参数超出范围
4.TypeError:类型错误。参数或变量不是预期类型发生的错误
5.URIError:URL错误。主要是相关函数参数不对
6.EvalError eval():函数执行错误。
13.js的作用域有哪些?
全局作用域
函数作用域
块级作用域
14.object.keys跟for in 跟object.getOwnPropertyName有什么区别?
object.keys是返回自身可枚举属性的数组。
for...in 除了返回自己可枚举属性还要返回继承来的可枚举属性的数组。
object,getOwmPpropertyName:返回自身所有属性名(包括不可枚举)
- 介绍一下promise
- 说一下promise.all跟promise.race的区别
- 手动实现一个promise.all。
- async/await 实现原理是什么
- for…in除了遍历自身可枚举的属性还能遍历其他的吗?如果只想用for…in遍历自身可枚举的属性呢
- 怎么实现一个深拷贝?
22. 使用lodash: _.cloneDeep(value);
23. JSON.Stringfy():先转换成字符串,再JSON.parse()反序列成一个新的对象
- JSON.Stringfy(obj)有什么缺陷??
1.如果obj里面有时间对象,利用JSON.Stringfy()转出来只是字符串,不是一个对象。
2.如果obj中存在正则缩写,则会转成空对象
3.如果obj中存在函数或者undefined,有可能会丢失
4.NaN/无穷大/无穷小会被转为 null
- 原生一个深拷贝呢?有什么思路吗
- 那循环复杂引用类型怎么处理呢
- 讲一下节流跟防抖呢
节流:触发高频事件时,n秒内控制事件触发次数,以稀释事件触发的频率。是一定会执行函数
防抖:触发高频事件时,设置固定时间触发事件,触发时间以最后一次触发的时间点开始计算。不一定会执行该函数
- 如何原生实现节流跟防抖呢
function throttle(fn, delay){
let timer;
return (...args) => {
// 如果定时器存在,继续执行,不重新刷新定时时间
if(timer) {
return;
}
// 定时不存在,重新建立定时器执行函数,并清空上一次定时时间
timer = setTimeout(() => {
fn(...args);
timer = null;
}, delay)
}
}
function debounce(fn, delay) {
let timer;
return (...args) => {
// 不管定时器是否存在,都以当前时间点重新创建定时器。(重新刷新定时时间)
clearTimeout(timer);
timer = setTimeout(() => {
fn(...args);
}, delay)
}
}
- 防抖内部传入的函数如果更新页面引发重新渲染,导致定时时间被重新刷新了,这怎么解决呢
把函数写在页面最外层
- Object都有哪些api呢
Object.is():判断两个值是否为同一个值
Object.entries():返回给定对象的[key, value]数组
Object.keys():返回给定对象自身可枚举键的数组。
Object.values():返回给定对象自身可枚举值的数组。
Object.fromEntries():把键值对列表转换为一个对象
- 知道发布/订阅模式吗?根观察者模式有什么区别呢?那怎么实现一个发布订阅模式呢?你遇到的哪些是发布订阅模式呢
发布/订阅模式是一种消息范式,是最常用的一种观察者模式的实现,发布者不会将消息直接传给订阅者,而是将发布的消息定为不同的类别,由其内部存在的调度中心将订阅者感兴趣的类型派发到订阅者手里。
同理,订阅者无需关心发布者如何发布消息,只需要订阅自己感兴趣的类型即可。
观察者模式:观察者直接订阅目标事件,在目标事件发生改变之后直接接收事件并做出响应
区别:发布/订阅模式的发布者和订阅者之间没有产生依赖关系,以事件通道作为桥梁。而观察者模式是直接订阅目标事件。
实现一个发布订阅模式:https://blog.csdn.net/lucky569/article/details/118542497
遇到的发布订阅模式: 事件监听
redux/mobx
Http协议
1.http常见的状态码有哪些?
http响应状态码用于指示特定HTTP请求是否已成功完成。响应分为五类:
1.信息响应(100-199)
2.成功响应(200-299)
3.重定向(300-399)
4.客户端错误(400-499)
5.服务器错误(500-599)
这里重点说一下常见的几个:
101---升级协议,如从 http 到 ws,此时需要反向代理支持
200---请求成功
301---永久重定向。http转向https时可能会用到301,此时浏览器会自动缓存,下次直接跳转,不再请求服务器。
302---暂时重定向,请求的资源临时从不同的URI响应请求
400---请求错误,无法被服务器理解,或者请求参数有误
401---当前请求需要用户验证,此时携带正确的权限凭证再试一次可以解决问题
403---禁止访问,无论权限凭证是否正确
404---未找到资源,有可能是接口写错了
405---请求方法错误,如:post请求写成了get
500---服务器内部错误
502---服务器繁忙,后端在重启或者大量流量导致服务器忙,稍等一下说不定就可以了。(已与后端建立链接)
504---网关超时,一般是指ngnix做反向代理时链接的服务器tomcat无响应导致的。
2.什么是跨域?如何解决跨域?
跨域是由于浏览器的同源策略引起的,所谓同源策略是浏览器的一种隔离潜在恶意文件的安全机制。即同协议/同域名/同端口,三者只要其中一种不符合,即为跨域。
解决跨域的方法主要是三种:JSONP,proxy,CORS,
JSONP:在html标签里,script/img这样的获取资源的标签是没有跨域限制的,但是JSONP只能发送GET请求。
JSONP原理:利用script标签的src,通过将前端方法(get)作为参数传递给服务器端,然后服务器端注入参数之后再返回给前端,实现通信
proxy(设置代理):前端请求的时候还是用前端的域名,通过代理将请求转发到真正的后端域名上面。(ngnix或者http-proxy-middleware)
CORS(跨域资源共享)Cross-origin resource sharing:只需要向响应头header中注入HTTP头部(Access-Control-Allow-Origin)让浏览器与服务器进行沟通,从而决定请求响应是应该成功还是应该失败.
3.简述HTTP的缓存机制?
http主要是使用cache-control来设置缓存,分为强制缓存跟协商缓存。
cache-control:no-store 不缓存
cache-control:no-cache , max-Age = 100 强制缓存,通过max-age来设置过期时间。不需要每次都去向服务器校验新鲜度。
cache-control:no-cache 协商缓存,每次都需要向服务器去校验新鲜度,通过看Etag跟last-modified来判断是否有更新。
4.发起HTTP请求的方法你用过的有哪些?它们的区别是什么?
5.说一下Cookie, LocalStorage 与 SessionStorage?
cookie很小 大小限制为4kb,通常用于存储用户登陆信息,每次都会携带在http请求头中(数据过多会存在性能问题),一般由服务器生成,可设置失效时间,不设置默认是浏览器关闭之后失效。
localStorage:大小为5MB,仅在浏览器保存,不与服务器通信。除非手动清除缓存,否则会永久保存,可以用来跨页面传参。
sessionStorage:大小为5MB,仅在浏览器保存,不与服务器通信。仅在当前会话下有效,关闭页面或者关闭浏览器之后就被清除了。用来保存一些临时的数据,防止用户刷新页面之后丢失了一些参数。
6.cookie有哪些属性,分别有什么作用?
cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同意服务器再发起请求时被携带并发送到服务器上
cookie的生命周期:
1.会话期Cookie:浏览器关闭即自动删除
2.持久性Cookie: 取决于过期时间(Expires)或有效期(Max-Age)指定的一段时间。
如何保证cookie被安全发送且不会被意外访问呢?
1.secure属性:设置后cookie只应该通过被https协议加密过的请求发送给服务端。(即使标记了secure也不能通过cookie传输敏感信息) ====》可以使用〉__Host__ 和 __Secure__来做cookie前缀,表示被Secure标记,后者限制弱于前者。
2.HttpOnly属性:此类cookie只作用于服务器,js无法访问带有该属性的cookie。
那么,cookie又允许发送给哪些URL呢?
1.Domain属性:指定了哪些主机可以接收cookie。默认值为origin(不包含子域名)。指定Domain则包含子域名,相对限制较小。
2.Path属性:指定了主机下的哪些路径可以接受cookie.(该路径必须存在于请求URL中,以/分隔)
3.sameSite Cookie允许服务器要求某个cookie在跨站请求时不会被发送。(从而可以阻止跨站请求伪造攻击CSRF)
sameSite接收三个值:
1> None :浏览器会在同站/跨站请求下继续发送cookie,不区分大小写。
2> Strict:浏览器只在访问相同站点时发送cookie;
3> Lax: 与Strict一样,(用户从外部导航至URL时除外) -默认值
7.如何设置一个支持过期时间的localStorage?
8.Ajax 原理。
原理: xmlHttpRequest
AJAX过程为:
1. 创建一个AJAX对象
2. 创建一个新的http请求,并指定发起请求的方法,URL以及验证信息
3. 设置响应请求状态变化的函数
4. 发起http请求
5. 获取异步调用返回的函数
6. 实现局部刷新
创建:var xhr = new XMLHttpRequest() || new ActiveObject("Microsoft.XMLHTTP")
注:前者所有现代浏览器,后者老版本(IE5,IE6)
发送请求:xhr.open(method,url,async)
注:参数一:方法,参数二:URL信息,参数三:异步否
xhr.send() //发送
监听状态:xhr.readyState // 返回请求的状态码
xhr.onreadystatechange = function(){}
注:每次状态改变都会调用该方法
响应:xhr.responseXML----服务器响应的若是XML,则使用该属性
xhr.responseURL---返回响应的序列化URL(若为空,则返回空字符串)
xhr.responseText-----非XML则使用
// 综合方法
$.ajax({
url:'http://xxxx', //请求地址
data:'count=25&maxid=2937193', //发送的参数
type:'GET', //请求方式,默认为get
success:function(data){ }, //请求成功的回调
error:function(){} //请求失败时的回调
});
9 .了解过TCP协议吗?讲一下三次握手、四次挥手。
TCP协议:是一种面向连接的、可靠的字节流服务。仅有两方进行通信,不能用于广播或多播。
三次握手:目的连接服务器,指定端口,建立TCP连接。
客户端跟服务器端建立连接时,先由客户端向服务器端发起一个连接请求,携带一个SYN为1的包,指明要连接的服务器端口号。
服务器接收到客户端的请求之后,发送携带自身序列号且标志位都为1的SYN-ACK确认包,确认客户端是否要建立连接。此时进入半连接状态。
客户端再次收到响应包,并向服务器发送SYN为0,ACK为1的响应包。当服务器接受到该包时,结束握手,建立连接。
四次挥手:改进版的三次握手。客户端向服务器请求关闭连接,
首先客户端携带FIN为1的包向服务器发起请求,表示自己没有数据传输但可以接受数据,进入等待状态。
服务器收到请求之后,向客户端发送一个确认包,表示自己收到关闭请求但是还没有开始关闭连接。
服务器准备好关闭连接之后,向客户端发送一个携带FIN为1的请求,表示自己准备关闭连接。
客户端收到关闭连接确认后,发送一个确认包,并设置一个固定等待时间。如果到了固定等待时间还没有收到服务器的ACK,则认为服务器已经关闭连接,于是挥手结束,关闭连接。
衍生SYN攻击:即攻击客户端在短时间内伪造大量不同的IP地址向服务器不断的发送SYN确认包,服务器不断的恢复确认包,导致正常的SYN包被丢弃,从而形成SYN攻击。
检测SYN攻击:在服务器上看到大量半连接状态且源IP地址是随机的,即为攻击。
预防SYN攻击:在服务器上设置最大半连接数
缩小超时时间。
TCP keep-alive:不定时的向对端发送探测包,收到ACK包则默认还连接,尝试几次无果则默认丢弃该连接
10 . 了解过websocket吗?有什么特点?对比http有哪些异同呀?实现原理是什么?
websocket:是一种基于TCP的全双工通信的协议,服务器与客户端都能主动互相通信的协议。
特点: 1. 建立在TCP连接之上
2. 与Http有良好兼容性,默认端口也是80/433端口,握手阶段可以通过http协议代理。
3. 可以发送文本/二进制数据。
4. 没有同源限制,客户端可以随意跟服务端通信
5. 协议标识符是ws,加密后的是wss,服务器网址就是url:ws://test:80/some/path
区别: http是单向协议,,一个request只能有一个response,且response是被动的; ws是双向通信。
http2.0推送消息只能推送静态资源,无法推送指定的信息。
相同点:都是基于TCP/IP的可靠传输协议,都是应用层协议
实现原理:建立长连接,服务器主动向客户端发起请求
ps:websocket仅仅是利用了http协议做连接请求;websocket之所以能持久连接的原因:它运行在TCP协议上,TCP协议自身是长连接协议;
http的keep-alive:设置超时时长和最大请求数。是处理多个请求把多个HTTP请求合并为一个。
11.samesite是干嘛的?
sameSite是cookie的一个属性值,用来禁止向第三方发送cookie。可有效防止CSRF(跨站请求伪造攻击)
其属性值包括:Lax --- 默认值 :不允许向第三方发送cookie(从外部站点导航至URL时(如链接)除外)
Strict--- 只能在相同站点下发送cookie
None --- 允许向本站或第三方站点发送cookie
12.怎么区分同域还是同站?
13.cookie了解吗 讲一下缓存呢
cookie 由服务器请求头携带,大小约为4KB,可通过expires,max-age:-1设置过期时间.
如果不设置过期时间,即为会话期Cookie,页面关闭就没有了。
localStorage:大小为5MB,仅在浏览器保存,不与服务器通信。除非手动清除缓存,否则会永久保存,可以用来跨页面传参。
sessionStorage:大小为5MB,仅在浏览器保存,不与服务器通信。仅在当前会话下有效,关闭页面或者关闭浏览器之后就被清除了。用来保存一些临时的数据,防止用户刷新页面之后丢失了一些参数。
14.etag有了解吗,为什么会有etag的出现?
Etag是资源特定版本的标识符,简单来说也就是标识资源有没有发生修改的。在协商缓存中需要不断的去向服务器校验新鲜度。
last-modified可能会存在短时间内检测不到资源修改的误差(比如30ms内修改了某个值,但是last-modified存在误差就会认为没有修改,返回304.);Etag的出现是为了更精确的标识资源的变化,每次资源发生变化都会生成一个新的hash值。对比两次hash值即可精确表示资源是否被修改。
15.简单配置过ngnix吗
性能优化
1.如何提高网页的加载速度。
2. 大屏针对echarts怎么做优化(按需加载)
3. 减少页面白屏的时间
4. 怎么查看打包过后的js体积
配置webpack-bundle-analyse,先npm install,然后在cra的configjs文件中配置plagin参数addBundleVisualizer,第二个参数为false,打包完自动打开解析页面。
- 怎么优化js打包过后体积大?
1.可以压缩静态资源图片,
2.terser压缩混淆化js代码体积。
压缩js代码的方式: 使用minfy
主要为把变量名简单化,比如把name压缩成a。
去除代码中的空格,换行符。
设置topLever,预执行函数。
3.服务端gzip压缩js代码
4.按需引入模块,利用bable-plugin-import完成。
5.利用webpack-bundle-analyze分析打包体积,替换体积过大的库,如moment.js ---> day.js
6.利用webpack的splitChunkPlugin将运行时使用多次的库打包到一起,避免一个包被多次使用,重复打包。
- 针对前端 你做过哪些优化?
- 关于代码规范这一块,你们是怎么做的呢?
React
1.react/vue中的key有什么作用?如果没有,会怎么样呢?
无论是react还是vue,key都是起到一个唯一标识的作用。在条件渲染中通过对key的索引来实现有针对性的修改dom节点,从而减少频繁操作dom树。例如在react中是通过diff算法索引key值来相对的渲染DOM节点,如果没有key的存在,每次的渲染需要去遍历整个dom树,然后再对比出有改动的地方,再去渲染,这样无疑增大性能消耗。那么....是不是一定要有key的存在呢? 答案也不是,一些不会影响DOM节点发生更改的操作直接去修改更为方便。比如只是修改文本内容。
ps:在循环的时候最好不要将index直接设为key。
推荐一个大佬写的很详细且清楚的地址:https://www.oecom.cn/reactkey/
2.setState是同步还是异步的?
其实严格来讲,setState并没有同步异步的概念。只是再react的实现机制中,使用变量isbatchUpdate(默认值为false)来触发setState的执行;使用batchedUpdates方法修改isBatchingUpdates变量为true,再去更新state,从而表现出来是异步。
setState为同步时有以下几种情况:
1.在setTimeout中使用
2.在原生的DOM操作中使用
3.使用setState回调函数。
3.什么是hook,为什么要使用hook?
hooks又叫钩子函数,是react16.8新增的特性,能够让帮我们“沟入”React state和生命周期的函数。
使用原因:
1.class组件难以理解,要使用class组件🉐️先理解js的this指向。‘
2.组件的逻辑状态难以复用。比如在class中的component里面数据获取,或者做一些数据操作,在复用该组件会有些不方便。
3.组件层次太深,嵌套地狱(比如高阶函数。)
4.react-hooks 为什么不能在if条件判断里面使用?
hooks的使用规则:
1.只在最顶层使用Hook(不要在循环,条件或嵌套函数中调用hook,确保hook在每一次渲染中都能按照同样的顺序被调用)
2.只在react函数中调用Hook(不要在普通的js函数中调用hook,确保组件的状态逻辑清晰)
原因是react里面是无状态的,所以hooks的执行是根据写的位置顺序来触发的。如果在if条件判断里面执行Hooks会导致hooks存在不执行的情况从而打乱原本的执行顺序。
5.react事件循环机制?
6.react中你做过哪些优化?
1. React.memo: 对props进行浅比较,复用上一次的渲染结果。
场景:父组件中包含子组件,当父组件的props新旧对比发生改变即时子组件的props并未改变,也会引发子组件的重新渲染,增大性能消耗。React.memo主要就是针对这个来做优化的,只有自身props发生改变的时候才会重新渲染,不会随着父组件的刷新而重新渲染子组件。从而降低性能开销。
2. useMemo():钩子函数,接收一个创建函数跟依赖项数组,对函数的返回值进行记忆(memorized值)。仅依赖项发生改变才会重新计算memorized值,否则复用上一次的计算结果,避免重复渲染。
3. useCallBack():钩子函数,接收的是一个回调函数跟依赖项数组,对函数进行记忆(memorized函数),该回调函数仅在某个依赖项改变时才会更新。
4. 循环生成dom节点时,为每个节点设置不同的key值,减少遍历次数。
7.react router的模式了解吗?
8.react怎么识别是一个组件还是原生标签呀
9.说一下你理解的setState;
10.react内部如何实现setState的异步呀
11.讲一下批量更新呢
12.兄弟组件之间的传值是怎么做的呢
13.那怎么修改context里面的值呢
14.React.memo useMemo有什么区别
15.React.createRef 跟useRef有什么区别
16.Redux了解吗?答:简单了解过,我们用的是mobx
17.那具体说一下mobx呢
职业规划
你对自己有什么打算?比较喜欢哪个领域呢