前端面试汇总

55 阅读13分钟

第一次发布文章~有点小激动,哈哈~~~~

最近面试总结的这些面试题, 这只是一部份,面试中除了问这些基本知识,还问到了项目中的一些功能是如何实现的,当场也会出一两个需求让你想想有什么思路去实现,以下有哪些写的不对的地方,望各位多多指出~

一.谈一谈vue

vue是动态构建用户界面的渐进式框架,项目中一般会用到vuex,vue-router技术,采用模块化开发

1.vuex是做什么用的呢?主要是为了实现多个组件共享数据的集中式管理工具,在数据通信中会使用到vuex,可以实现任意组件间通信,它包含了几个核心,state,actions,mutations,getters; state是用来初始化数据, mutations是用来直接操作数据的方法, actions是间接操作数据,一般用来发送请求, getters是用来计算只读性属性,若组件要使用到vuex的数据,可以通过this,$store.state/dispacth actions/commit mutations/getters或mapState,mapActions,mapMutations,mapGetters可以获取到

2.vue-router是为了实现单页面应用,点击页面不会刷新,只会局部更新,使用router-link相当于a标签实现路由跳转,router-view可以显示路由组件,然而项目中路由传参方式一般用的比较多的是params,和query参数,通过this.$route.params/query可以获取到,是在route路由配置中设置,也可以使用props,命名路由,给相同层级的路由组件传递公共参数,route是用来获取参数,router是可以用来跳转,项目中用的比较多还有全局路由守卫是为了路径发生变化时,通过数据劫持,监视是否发生变化,通过routes寻找对应的组件

3.MVVM设计模式:

m:model数据层,v:view视图层,vm:viewmodel视图模型层,数据由viewmodel控制,可以从数据层读取数据,加载到页面,这时由model--->view层,也可以从view层读取要修改的数据,修改数据层的数据,此时由view--->model层,这样就实现了双向数据绑定

4.vue响应式原理

分为三个部份,第一是数据代理,第二是数据劫持,最后是模板解析

简单版本:数据发生变化,页面也会变

1.数据代理:将data中数据代理到实例对象上,遍历所有数据,通过object.definedProperty()方法重新定义属性,内部通过get方法获取数据,set方法设置新值,实际操作是原数据的数据

2.数据劫持:遍历所有data中的数据,将其定义为响应式数据,通过object.defineProperty重新定义get和set方法,这个时候通过闭包可以保存一个dep对象,get中将来通过dep会建立响应式联系,set可以触发响应式更新

3.模板解析

(1)将元素节点转换成文档碎片节点

(2)解析模板

取出当前节点进行遍历,判断是元素节点还是文本节点

若是元素节点就要编译,并且取出所有属性,判断是否是指令属性,若是再判断是否是事件指令

若是,就给元素绑定事件,回调函数可以通bind方法强制改变this指向

若是普通指令,new watcher触发响应式联系

若是文本节点,就解析插值语法

(3)将解析完的模板代码添加到页面中生效

5.双向数据绑定原理

是通过v-model实现数据绑定

是给元素绑定value属性和input事件

当用户输入数据时,会触发input事件,将data中值为e.target.value实现双向数据绑定

二.谈一谈ajax

使用ajax发送请求与服务器进行交互,不会刷新整个页面,只会局部更新,但是会存在跨域问题 什么是跨域?违背了同源策略(协议,域名,端口号都相同)

解决跨域问题的方法:

1.jsonp是通过创建script标签,src属性添加一个回调,再把script标签添加到body中

2.cors是在响应头那里设置字段,设置access-control-allow-origin允许跨域的地址

3.proxy数据代理在vue.config.js文件中配置,devserve对象中配置

ajax请求会返回promise对象

promise有三个状态,pending,resolved,rejected,调用resove函数,会由pending状态变成resoved状态,调用reject函数,会由pending状态变成rejected状态,状态只能修改一次,promise它有then方法和catch方法,then方法中return一个值,或是一个promise对象,或没有return,那最终会返回成功状态的promise对象,若return一个失败的promise对象或抛出错误,那会返回失败状态的promise对象,

一般项目中用的比较多的还是async和await,因为它会返回一个promise对象,async是声明函数是异步的,await是只等待promise对象执行,等异步执行完成,这样就可以利用promise的一些方法去判断返回值,若等待的是返回成功状态的promise对象,则就返回promise对象,若是失败状态的则不执行

三.谈谈localStorage,sessionStorage,

这两个是为了缓存数据,还有一个cookie也是

cookie只能存储4kb左右大小的文件,若没有设置超时时间,关闭浏览器就会失效,若设置了超时时间则等到了超时间时才会失效,会存在内存中

sessionStorage可以存储5Mb左右的文件,临时性存储,存在内存中,关闭浏览器就失效了

localStorage永久性存储,存储文件大小是20mb,只要用户不清除缓存,可以永久保存,存在硬盘中

项目中一般在设置token也就是用户登录的标识那里,会把token保存在缓存中,以便用户下次无需重新登录,可以从缓存中读取数据了

四.bom和dom以及es6新特性

javascript是由bom,dom,ECMA组成的,bom是浏览器模型,操作浏览器的,dom是文档对象模型,用于操作dom节点,ECMA是语法规范,项目中可以创建节点,插入节点,复制节点,获取元素等操作 es6新特性: 我一般用的比较多的是解析对象,解析数组,通过rest扩展运算符,获取参数,就不会使用arguments获取了 数组的方法(push后添加,pop后删除,unshift前添加,shift前删除,filter过滤,map映射,reduce,split切割数组,join添加变成字符串等)通过模板字符串,对一些数据引入使用,箭头函数这个用的比较多

箭头函数没有this指向,它的this是距离包裹它的函数,若是普通函数或自调用,那this指向window,若是实例化调用,那指向实例化对象,若是隐式调用则this指向上下文对象,若是call,apply绑定那就是call,apply所规定的那个对象

call,apply都是可以this指向的,只是写法上有些不同,call是用逗号隔开参数,apply是用数组隔开参数,还有bind方法也是改变this指向,但没有调用,会返回一个新函数

还有let,const声明变量的方法,都是只能在块级作用域中生效,不能重复声明,声明了必须赋值,但是let声明的值是可以修改的,const声明的值是不能修改的

在js中用到var声明变量,是可以重复声明,后面的会覆盖前面的,可以分为全局变量和局部变量

可能会问什么是作用域?(那可以延伸到原型链)

它就是查找所有变量和函数的一系的过程,若自己身上没有这个变量,可以通过作用域往上一层作用域查找,直到找到为止,若没有找到就会报错,其实它底层实现跟原型链类似,因为构造函数会有prototype属性指向它的原型对象,原型对象的constructor构造器会指回构造函数,其实只要是new出来的就是构造函数,那实例对象上会有一个__proto__属性指向构造函数的原型对象,通过__proto__这种隐式原型的方式 就形成了原型链,若查找变量时自身上没有就可以沿着原型链去查到,最终找到object构造函数的原型对象,因为它的proto是为null

五.数据类型

那基本数据类型包含:string,number,boolean,null,undefined,symbol,bigint

引用,复杂数据类型有:object,function,array

六布局

响应式布局就是采用@media媒体查询方法使页面能够随着屏幕的大小发生变化

左边固定右边自适应布局

1.可以通过position定义,父元素relative,子元素absolute,left:z-index:1,right:margin-left:xxxpx

2.可以通过float浮动,left,right都向left浮动,然后left:margin-left:-100%;right:margin-left:xxxpx

3.也可以通过flex布局,父元素display:flex,子元素display:flex,flex-direction:column

七.后台项目动态添加路由如何实现的

根据用户权限来动态展示路由,其实就是获取用户数据做判断是否有权限,有权限就可以展示相应路由,然后用户对应的路由列表就可以渲染出来

八.深度克隆的方法

1.const newObj=JSON.parse(JSON.strigify(obj))

2.function checkType(obj){

return Object.prototype.toString.call(obj).slice(8,-1)//获取原型上的方法并

}

function deepClone(obj){

let re;

if(checkType(obj)===object){

re={}

}else if(checkType(obj)===Array){

re=[]

}else{

return obj

}

for (let in obj){

re[i]=deepClone(obj[i])

}

return re

}

九.pc端支付页面如何实现的?

提交订单跳转到支付页面,选择支付方式,若你选择支付宝,发送请求把当前的订单数据传给服务器,跳转到支付宝的页面;如果用户扫码支付成功,支付宝会通知服务器支付结果,同时把重定向到我们的页面,重定向地址需要后端人员提前配置;重定向到订单页面,会在mounted中发送请求,请求最新的订单信息,在这个时候请求回来的数据就能看到所有订单的支付状态

十.封装过什么组件,怎么实现的?

轮播图,引入轮播图进行二次封装,三级分类列表,分页器

分页器组件的实现

首先设置好当前页,每页的显示的条数,显示的按钮数量

其次用watch监视页码发生的变化(组件中使用绑定事件,封装组件中触发)

用computed计算属性,计算总页数,中间显示的按钮值(计算开始和结尾的数进行判断)

进行遍历,得到按钮数量

十一.小程序opendId

通过wx.login获取code,用wx.request发送请求并把code携带上到服务器上

这时服务端可以向微信调用登录凭证校验的接口,然后返回session_key,opendId

若是自定义状态就和session_key,opendId关联起来,返回自定义登录的状态,把它存在storage中

若用户再次登录时,通过wx.request发起业务请求,携带自定义登录的状态,通过自定义状态查询到opendId,session_key,返回数据

十二.小程序支付流程

客户端下单支付发送请求给商家服务器

商家和微信服务器对接唯一标识

商家服务器根据opendId生成商户订单

商家服务器发送请求调用api获取支付订单信息

商家对预支付信息签名加密后返回小程序客户端

用户确认支付调用接口

微信服务器返回支付结果给小程序客户端

微信服务器推送支付结果给商家服务端

十三工作中遇到的难题:

之前有在computed直接修改data的数据,发现页面不会发生变化,应该使用get和set方法去获取和设置data那个变量,当computed监听数组变化的时候,要对数组进行操作的话,需要通过this.$set方法去修改数组,这样页面才会触发更新

十四.如何实现promise

创建new Promise

通过then,catch捕获promise对象的状态

通过返回值返回的状态

异步编程的优缺点:

非阻塞的IO更大程度的利用资源

十五.js事件轮询机制

同步代码:绑定事件,定时器,发送ajax

异步代码:事件回调函数,定时器的回调函数,ajax的回调函数

先执行同步代码再执行异步代码

原理:执行完同步代码之后,把相应的回调添加到管理模块中,事件回调添加到事件管理模块,ajax回调添加到ajax管理模块,等事件发生或计时器到期等,就会把相应的回调函数添加回调队列中等待执行,等初始化同步代码执行完毕之后,js引擎会循环检查回调队列中的回调函数,并执行

十六.http协议由哪些构成

请求方式,url,协议版本,请求体,响应体

缓存:dns缓存,计算机缓存,路由器缓存,运营商缓存

十七.水平垂直居中的方法

行内元素:line-height:xxxpx; text-align:center;

块元素:position:relative;top,left:50%;transform:translate(-50%,-50%)

display:flex;justify-content:center;align-items:center;

十八..sync怎么实现通信的

原来是父向子通信,后期在它的基础上实现子向父通信,通过绑定事件,接收子组件的数据,并触发事件,将最新数据更新到父组件中

十九.路由勾子函数

全局前置守卫beforeEach,全局解析守卫beforeResolve,全局后置钩子afterEach

路由独享守卫beforeEnter

组件内的守卫beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave

二十.keep-alive的实现

若组件需要缓存,通过keep-alive包裹起来,并设置include或exclude,缓存不活动的组件实例

keep-alive的生命周期顺序:

created-->mounted-->activated--->deactivated-->activated

二一.虚拟dom和真实dom的区别

真实dom会导致页面重绘重排,性能极低,体积大,无用元素多,占用内存大

虚拟dom不会引起重绘重排,渲染次数少,体积小,无用属性少,占用内存小

重绘重排:只要样式或尺寸发生了变化那就会引起重绘重排

二十二mixin混入

将组件中可复用的功能,定义一个混合文件写在一个js文件中,组件通过混合mixins:[xxx]引入并使用

二十三.自定义指令

除了内置指令,v-model,v-bind等

对普通dom元素进行底层操作,注册一个全局指令,或注册局部指令

若要创建一个自定义指令,可以用固定布局将元素固定在页面上,可以通过指令值去更新自定义指令

若props数据不能修改,可以设置dataset自定义属性