面试

前端常见问题总结

2019-12-02  本文已影响0人  小本YuDL

补:get请求传参长度的误区

补:get和post请求在缓存方面的区别


1.三次握手and四次挥手

image.png image.png

答:中间的两个动作没有合并,是因为tcp存在「半关闭」状态,也就是单向关闭。
因为当Server端收到Client端的syn连接请求报文后,可以直接发送syn+ack报文。其中ack报文是用来应答的,syn报文是用来同步的。但是关闭连接时,当Server端收到fin报文时,很可能并不会立即关闭,所以只能先回复一个ack报文,告诉Client端,"你发的fin报文我收到了"。只有等到我Server端所有的数据报文都发送完了,我才能发送fin报文,因此不能一起发送。故需要四步握手。

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。


2.url到页面渲染完成的经过

大致分为三步:


3.js引擎的执行机制

(1) JS是单线程语言
(2) JS的 Event Loop是JS的执行机制。

cosole.log(1);
setTimeOut(function(){
    cosole.log(2);
},0);
cosole.log(3);
执行的输出顺序是: 1  3  2

js是顺序从上到下执行,但是setTimeOut是最后才执行的,就证明了异步的存在。js也就将任务分为:同步任务和异步任务。

循环执行上述三步,直到执行栈为空,就是事件循环了

所以上面例子的执行顺序分析是怎样的呢?

console.log(1) 是同步任务,放入主线程(执行栈)里
setTimeout() 是 异步任务,被挂起, 0秒之后被推入消息队列里
console.log(3 是同步任务,放到主线程(执行栈)里

当 1、 3输出后,主线程去消息队列(事件队列)里查看是否有可执行的函数,执行setTimeout里的函数,输出2

以上就是event loop 的简单分析了。但是只是很浅的一部分,因为还有下面这样情况:

setTimeout(function(){
     console.log('定时器')
 });
 
 new Promise(function(resolve){
     console.log('开始for循环');
     for(var i = 0; i < 10000; i++){
         i == 99 && resolve();
     }
 }).then(function(){
     console.log('执行then')
 });
  console.log('执行结束');

对于这样多个异步的事件,按照之前的分析应该输出:开始for循环 --> 执行结束 --> 定时器 --> 执行then
但是实际的输出却是: 开始for循环 --> 执行结束 --> 执行then --> 定时器

会发现 是 先执行promise 再执行的setTimeOut ,那难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确。

而准确的划分方式是:

按照这种分类方式:JS的执行机制

重复以上2步骤,再结合前面的事件循环,就是更为准确的JS执行机制了。

所以上面例子的执行顺序分析是怎样的呢?

先执行script宏任务
遇到 setTimeOut 是宏任务,将其放入宏任务队列
遇到 new Promise直接执行,打印  "开始for循环"
遇到 then 是微任务,将其放入微任务队列
打印 "执行结束"
本轮宏任务(script)执行完毕,检查微任务队列,遇到then,执行输出 " 执行then",就只有这一个微任务,所以执行结束
本轮 event loop 执行结束
进入下一轮 
执行宏任务 setTimeOut,打印 "定时器"
再查看微任务队列,没有微任务
执行完毕

4.hash与history的区别

window.history.pushState(state,title,url)
  state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
  title:标题,基本没用,一般传null
  url:设定新的历史纪录的url。新的url与当前url的origin必须是一样的,否则会抛出错误。url可以时绝对路径,也可以是相对路径。
  如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成       https://www.baidu.com/a/qq/,
  执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/

window.history.replaceState(state,title,url)
  与pushState 基本相同,但她是修改当前历史纪录,而 pushState 是创建新的历史纪录

window.addEventListener("pospstate",function(){
   监听浏览器前进后退事件,pushState与replaceState方法不会触发
})
window.history.back()   后退
window.history.forward()   前进
window.history.go(1)   前进一部,-2回退两不,window.history.lengthk可以查看当前历史堆栈中页面的数量

这两个方法应用于浏览器的历史纪录站,在当前已有的back、forward、go 的基础之上,他们提供了对历史纪录进行修改的功能,只是当他们执行修改使,虽然改变了当前的url,但你的浏览器不会立即像后端发送请求

1、hash模式下,仅hash符号之前的内容会被包含在请求中,如 http://www.abc.com 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
2、history模式下,前端的url必须和实际后端发起请求的url一致,如http://www.abc.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。


5.vue钩子函数

(1)与生命周期有关的生命周期函数: beforeCreatecreatedbeforeMountedmountedbeforeUpdateupdatedbeforeDestorydestoryed
(2)computedwatchfilter
(3)自定义指令directive的钩子函数

常用参考链接:https://www.jianshu.com/p/8314ccd03fa9


6.vue常用指令

常用参考链接:https://blog.csdn.net/dz13271116886/article/details/99708315


7.vue常用修饰符

详细参考链接:https://blog.csdn.net/qq_42238554/article/details/86592295


8.vue常用组件

详细参考链接:sohu.com/a/328202078_120047065


9.vue 过滤器

在vue中提供了Vue.filter('filterName',fn)来定义一个过滤器。
过滤器可以在HTML代码中使用,对动态拿到的数据进行过滤
filter不会修改原始数据,它的作用是过滤数据。
通过|管道符来过滤前面数据

用法参考链接:https://blog.csdn.net/badmoonc/article/details/81485803


10.MVVM的理解

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。

响应式原理

观察者-订阅者(数据劫持):

实现方法:

过程描述:
(1) 当创建一个vue对象时,先进入初始化阶段:(两部分工作)
一方面:vue 会遍历data的所有属性,通过object.defineproprety()方法,将所有属性变成setter和getter。 另一方面:vue的指令编译器Complie会解析每个元素节点,初始化视图,然后由watcher(订阅者)更新视图,此时watcher会将自身添加到消息订阅器(Dep)中,初始化完毕。

(2) 当数据变化时:会触发 observer数据监听器中的setter方法,setter 会调用Dep中的方法,此时Dep会去遍历所有的订阅者,然后去调用订阅者的update方法,通知订阅者进行视图更新。

参考:https://segmentfault.com/a/1190000018399478


11.vue生命周期

Vue实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂在DOM、渲染-更新-渲染、卸载等一系列过程

详细参考连接:https://www.jianshu.com/p/672e967e201c


12.vue动态路由

在vue项目中,使用vue-router如果进行不传递参数的路由模式,则称为静态路由;
如果能够传递参数,对应的路由数量是不确定的,此时的路由称为动态路由。

比如在写商品详情页面的时候,页面结构都一样,只是商品id的不同,所以这个时候就可以用动态路由动态。

冒号后面就是动态的参数
路由配置:
const router = new VueRouter({
    routers:[
      {
        path:'/home:id'
        name:'home'
        component:home
      }
    ]
});

使用:
<template>
  <div>
    <router-link to="/home/10">衣服</router-link>
    <router-link to="/home/11">麻辣火锅</router-link>
    <router-link to="/home/12">肉夹馍</router-link>
  </div>
</template>

实现参数传递的方法:

  1. 使用query传参,name属性为要跳转的组件所对应的name,query为要携带的参数
<router-link :to="{name:'main','query':{data:'allData'}}"></router-link>
  1. 使用params传参,name属性为要跳转的组件所对应的name,params为要携带的参数
<router-link :to="{name:'main','params':{data:'allData'}}"></router-link>

3.设置页面默认的路由参数(query/params):

 this.$router.push( {name: 'main', 'query': {data: 'allData'} } )
this.$router.push( {path: '/main', 'query': {data: 'allData'} } )

13.post、get、put、delete

post、get、put、delete就像对应着数据库的CRUD(增、删、改、查)

    post             /url          创建
    delete           /url/xxx       删除
    put              /url/xxx       更新或创建
    get              /url/xxx       查询

(1) get请求,请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的,具有幂等性。

(2) put 请求,求是向服务器端发送数据的(与get不同)从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次put操作,其结果并没有不同,具有幂等性。

(3) post 请求,与put请求类似。都是向服务器端发送数据求会改变数据的种类等资源,就像数据库的insert操作一样,会创建新的内容。几乎目前所有的提交操作都是用POST请求的。不具有幂等性。

(4) delete 请求,用来删除某一资源,该请求就像数据库的delete操作。

put 与post 的共同点及区别?


14.跨域方法

详情链接:http://www.imooc.com/article/40074


15.vue插件(图表,excel)


16.callback、promise、async-await

请参考链接


17.map、reduce、filter、forEach

18.for、forEach、 for-in 、 for-of

小总结:

let  arr = {
  name:'aaa',
  age:23,
  sex:'女'
}
普通对象要加可枚举的属性Object.keys(),不然报错
for(let i of Object.keys(arr)){
  console.log(i);
}  //name age sex

for(let i in arr){
  console.log(i);
}  //name age sex

for-of 遍历 Map ,初始是一个二维数组,对应的键值匹配

let test = new Map([['name','aaa'],['age',12],['sex','女']]);
for (var [key, value] of test) {
  console.log(key +" is "+ value);
}
//name is aaa
//age is 12
//sex is 女

for-of 遍历 Set ,遍历同时会进行数组的去重

var test = new Set([1,1,2,3,4,5]);
for (var i of test) {
  console.log(i);
}
//1,2,3,4,5
上一篇 下一篇

猜你喜欢

热点阅读