第一次面试前端有点小紧张,面试官问的问题之前都有背过,但是由于紧张忘了怎么回答,所以保持好心态是前提 = =
1、状态码
HTTP状态码
1xx Informational(信息性状态码) 接受的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
(1)、200 OK: 表示从客户端发送给服务器的请求被正常处理并返回;
(2)、204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
(3)、206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx Redirection(重定向) 需要进行附加操作以完成请求
(1)、301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
(2)、302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
(3)、301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
(4)、303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
(5)、302与303的区别:后者明确表示客户端应当采用GET方式获取资源
(6)、304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
(7)、307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx Client error(客户端错误) 客户端请求出错,服务器无法处理请求
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx Server Error(服务器错误) 服务器处理请求出错
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
2、CSS居中
垂直居中的方式
行高=高
绝对定位 top50%,自身宽度的50%的负值
flex布局 align---center
水平居中的方式
绝对定位
flex布局 juest---center
margin 0 auto
text-align center
3、本地存储(如何解决刷新页面数据丢失)
本地存储的方式有哪些?区别及应用场景?
javaScript本地缓存的方法我们主要讲述以下四种:
- cookie
- sessionStorage
- localStorage
- indexedDB
区别
关于cookie、sessionStorage、localStorage三者的区别主要如下:
- 存储大小:
cookie数据大小不能超过4k,sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大 - 有效时间:
localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭 - 数据与服务器之间的交互方式,
cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端;sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
应用场景
在了解了上述的前端的缓存方式后,我们可以看看针对不对场景的使用选择:
- 标记用户与跟踪用户行为的情况,推荐使用
cookie - 适合长期保存在本地的数据(令牌),推荐使用
localStorage - 敏感账号一次性登录,推荐使用
sessionStorage - 存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况,推荐使用
indexedDB
4、深拷贝和浅拷贝
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
在JavaScript中,存在浅拷贝的现象有:
- Object.assign
- Array.prototype.slice()
- Array.prototype.concat()
- 使用拓展运算符实现的复制
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
常见的深拷贝方式有:
- _.cloneDeep()
- jQuery.extend()
- JSON.stringify()
- 手写循环递归
5、Promise
Promise构建出来的实例存在以下方法:
- then() 是实例状态发生改变时的回调函数,第一个参数是
resolved状态的回调函数,第二个参数是rejected状态的回调函数 - catch() 用于指定发生错误时的回调函数
- finally() 用于指定不管 Promise 对象最后状态如何,都会执行的操作
Promise构造函数存在以下方法:
- all() 用于将多个
Promise实例,包装成一个新的Promise实例 - race() 同样是将多个 Promise 实例,包装成一个新的 Promise 实例
- allSettled()
- resolve()
- reject()
- try()
6、数组常用方法
增
下面前三种是对原数组产生影响的增添方法,第四种则不会对原数组产生影响
- push() 接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度
- unshift() 开头添加
- concat() 首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组
删
下面三种都会影响原数组,最后一项不影响原数组:
- pop() 删除数组的最后一项,同时减少数组的
length值,返回被删除的项 - shift() 删除数组的第一项,同时减少数组的
length值,返回被删除的项 - splice() 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
- slice() 创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组
改
即修改原来数组的内容,常用splice
传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响
查
即查找元素,返回元素坐标或者元素值
- indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
- includes() 返回要查找的元素在数组中的位置,找到返回
true,否则false - find() 返回第一个匹配的元素
7、 css选择器权重
!important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
8、 bind、call、apply 区别
call,apply,bind都是改变this指向函数的方法
区别:
-
call后面需要传参以逗号隔开 例如 fn.call(car,’奔驰’,福特’)
-
apply后面需要传参以数组形势 例如 fn.apply(car,[‘奔驰’,’福特’])
-
bind需要传参和call一样,将函数作为返回值但是不会执行fn 例如
-
let fun = fn.bind(car,’奔驰’,福特’) fun()
9、Vue2和Vue3数据绑定的区别
原理:使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。
Vue2.0
语法:
Object.defineProperty(obj, ``"name"``, { get:()=> {}, set:()=> {})
参数一: obj:劫持对象,参数二:"name":劫持对象属性 , 参数三:给属性添加set,get方法
例子:
let obj = { name: "tom", age: 10 };
Object.defineProperty(obj, "name", {
get: () => {
console.log("访问了name属性");
},
set: (newVule) => {
console.log("设置了name属性");
},
});
obj.name; //触发get
obj.name = "jack";//触发set
vue3.0
原理:Vue3.0中的响应式采用了ES6中的 Proxy 方法。Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)
语法:
let p = new Proxy(obj,{get:(target,prop,p)=>{},set:(target, prop, vaule, p)=>{}})
参数一: target:劫持对象,参数二:prop:劫持对象属性 , 参数三:vaule:新的属性值, p:本身 列子:
let p = new Proxy(obj, {
get: (target, prop, p) => {
console.log("获取");
return prop in target ? target[prop] : "默认值";
},
set: (target, prop, vaule, p) => {
console.log("设置");
target[prop] = vaule;
},
});
console.log(p.name); //访问了name属性
console.log((p.name = "java" )); //设置了name属性
总结:
vue2通过Object.defineProperty劫持的是对象中每一个属性
vue3通过Proxy劫持的是对象中每一个属性
10、宏任务和微任务
什么是宏任务和微任务
- 宏任务包括:setTimeout setInterval Ajax DOM事件
- 微任务:Promise async/await
- 微任务比宏任务的执行时间要早
代码
console.log(1)
setTimeout(function() {
console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {
resolve(1000)
})
p.then(data => {
console.log(data)
})
console.log(3)
结果是: 1, 3, 1000, 2
画的有点乱, 下面带你梳理一下执行顺序:
- console.log(1) 是同步任务, 所以立即执行. (代码 ---> 执行栈 ---> 输出区域)
- setTimeout是宏任务, 所以等微任务做完在执行. (代码 ---> 宏任务队列)
- promise.then是微任务, 所以等主线程执行完毕在执行. (代码 ---> 微任务队列)
- console.log(3) 是同步任务, 所以立即执行. (代码 ---> 执行栈 ---> 输出区域)
- 现在主线程上面的任务全部执行完毕, 然后执行微任务队列的任务, 输出console.log(data)
- 现在主线程上面没有任务, 微任务队列也没有任务, 这才这些宏任务队列, 输出console.log(2)
console.log(1)
setTimeout(function() {
console.log(2)
new Promise(function(resolve) {
console.log(3)
resolve()
}).then(function() {
console.log(4)
})
})
new Promise(function(resolve) {
console.log(5)
resolve()
}).then(function() {
console.log(6)
})
setTimeout(function() {
console.log(7)
new Promise(function(resolve) {
console.log(8)
resolve()
}).then(function() {
console.log(9)
})
})
console.log(10)
这个代码太长, 画就很混乱, 直接梳理:
-
- console.log(1) 同步任务, 直接执行, 输出.
-
- setTimeout宏任务, 直接丢入宏任务队列.
-
- promise本身不是一个微任务, then才是; 所以console.log(5) 同步任务直接执行输出, 遇到then微任务, 丢入微任务队列
-
- setTimeout宏任务, 直接丢入宏任队列
-
- console.log(10) 同步任务, 直接执行, 输出.
-
- 主线程执行完毕, 再来执行微任务队列; 第一个进来的console.log(6) 执行输出
-
- 微任务队列执行完毕, 执行宏任务队列; console.log(2) 第一个进来执行输出, 下面console.log(3) 同步任务执行输出.
-
- 遇到then, 所以console.log(4) 丢入微任务队列
-
- 现在主线程是空的, 微任务队列中有console.log(4), 宏任务队列也有任务; 微任务优先级大于宏任务, 所以先执行console.log(4)
-
- 现在主线程是空的, 微任务队列也空了, 宏任务队列中还有第二个setTimeout
-
- console.log(7) 同步任务, 直接执行输出
-
- console.log(8) 同步任务, 直接执行输出
-
- 遇到then, console.log(9) 丢入微任务队列
-
- 主线程为空, 执行微任务队列, 输出console.log(9)