2021中级前端面试总结
自我介绍
面试官下午好,我叫**,今天来应聘贵公司的前端工程师岗位。我从事前端开发两年多,有X年多的Vue开发经验,一年React开发经验,在上家公司主要从事H5页面,后台管理系统,混合App等项目开发。平常喜欢逛一些技术社区丰富自己的技术,像思否,掘金之类,并且自己也独立开发了个人博客网站,记录自己的工作总结和学习心得。 我的性格比较温和,跟同事朋友相处时比较外向,在工作中代码开发时我喜欢全心全意的投入,对于工作我总抱着认真负责的态度。面试官,以上是我的介绍,谢谢。
继承
1,原型继承
主要缺点内存共享,共用一个原型对象,实例1上修改了属性,实例2的属性也会跟着变。
2,借用构造函数继承
在子类型构造函数内调用父类型构造函数,主要缺点为父类上自己定义的方法子类访问不到
3,组合继承
把上述两种继承结合起来,避免了上述方法的缺点但是会调用父类构造函数2次,浪费性能。
4,寄生组合继承
通过object.creat()的方法,继承的同时只拿原型上的东西,不拿实例this上的东西。
5,es6继承
class extend super
作用域
全局作用域,函数作用域,块级作用域
作用域链
从当前作用域一层一层向上寻找某个变量,直到到全局作用域还没找到就放弃。这一层层的关系就是作用域链。
浏览器渲染
html被html解析器解析成DOM树,css被css解析器解析成cssom树,生成渲染树(render-tree),再生成布局,将渲染树的节点平面化,将布局绘制再屏幕上。
同步异步
js执行机制是单线程的,耗时(异步)任务委托给宿主
1,主线程判断是否是同步还是异步,同步自己执行,异步委托给宿主浏览器执行
2,异步任务依次按执行顺序进入任务队列,执行完同步任务后,浏览器依次执行异步任务。
3,异步任务还分为宏任务,微任务,宏任务由宿主发起的比如定时器,那微任务是js自身发起的,先执行宏任务,执行完宏任务看看微任务队列中是否有微任务,执行完微任务队列中的微任务再执行下一个宏任务。
闭包
函数处理完后,内存没有被回收就是形成了闭包。
两个函数,一个函数,访问另一个函数内部的属性就会形成闭包。
优点,延申变量作用域范围。
缺点,占用内存,造成内存泄漏
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行 ——《你不知道的JavaScript》
原型链
访问一个对象的属性时,如果对象内部不存在这个属性,原型属性—proto—就会去这个构造函数的原型对象上找prototype.。原型对象又有自己的原型属性,该原型属性(—proto—)又去对象(object)的原型对象(prototype)上找,还是没有的话对象的原型属性最终指向null
跨域
- jsonp(利用script标签没有跨域限制的漏洞实现。缺点:只支持GET请求)
- CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)
- Node中间件代理
- Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。
this指向
1,全局作用域,普通函数this指向window
2,方法调用,谁调用这个方法指向谁
3,构造函数的this指向实例
BFC
是css布局的一个概念,该环境内的元素不受外部影响
1,出现的问题
父元素高度塌陷,元素之间外边距重合,文字环绕问题
2,解决办法
清除浮动overflow:hiddren 这个比较常用.给元素加定位。元素设置浮动。
promise
是一个构造函数,promise.prototype包含一个.then()的方法。const p=new Promise()出来的的实例有p.then的方法,里面可以执行成功或者失败的回调函数。
缓存
浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为
堆栈
简单数据类型的值存在栈里直接能拿,复杂数据类型(引用类型 )的值在堆里,在栈里的是地址。通过地址指向值。堆里的值修改后影响多个对象。
call,apply,bind
1,都可以用来改变函数内部this指向,第一个参数为this指向谁
2,call和apply都会调用函数,apply接受数组,bind不会调用函数
get和post
get再浏览器中回退不会再次请求,post会。
get再url传递参数有限制,post没有限制。
get没有post安全,get参数暴露在地址栏,post时放在报文内。
get一般用来查询信息,post用来修改信息。
http和https
http的头时http。
http没有https安全。
http的标准端口是80,https是443.
https对传输的数据有加密,非对称加密。
https需要CA机构的ssl证书
css盒子模型
所有HTML元素可以看作盒子,在CSS中,box model这一术语是用来设计和布局时使用。 CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。 盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。
网络安全
xss跨脚本攻击,代码注入攻击会读取cookie,session tokens。执行一些而已代码。。避免:url参数使用encodecomponent方法转义,
尽量不要有innerhtml插入html内容。使用特殊字符。
vue
nextTick
vue更新dom是异步的,可以用this.$nextTick获取更新后的dom,也可以在updated中访问到。
传值
父->子组间传值,在子组件中用props接收。
子传父用$emit,通过方法来触发一个自定义事件,需要传的值作为第二个参数,父组件中的子组件标签上绑定对这个自定义事件的监听。
mvc
m代表数据层,v代表视图层,c代表控制层。
1,视图层v变化触发控制层c,将数据传到控制层c,
2,控制层c拿到新数据触发数据层m,并将更新的数据床给数据层,
3,数据层拿到新数据并触发视图层的更新。
mvvm
将controller演变为viewmodel,viewmodel双向绑定了数据层和视图层,数据变化自动同步视图,视图变化自动同步数据。
提高了性能,减少了相对与mvc的大量dom操作,耦合少,view和model是完全分离的,通过viewmodel双向绑定。
路由
声明式(标签跳转)router-link-to
编程式(js跳转)this.$route.push
生命周期
created:创建完成,data中有值,但是未挂载。常用来发起异步请求。
mounted:挂载完成。能操作dom。
updated:更新完成。能获取更新后的数据。
destroyed:一般在销毁前beforedestroyed回手动销毁解除事件监听等。
杂项
v-show和v-if,v-if是通过销毁和创建dom的,v-show是通过display的显示隐藏。
包裹组件,可以保留组件状态,避免重新渲染。
样式只在当前组件起作用。
VNode是指vue的‘虚拟节点’。
虚拟DOM是Vue组件树建立起来的整个VNode的称呼。
vue中通过索引修改数组页面不会更新,用vue.set才行。改变原数组才会触发页面更新。或者用新数组替代原数组。
避免v-for和v-if用在一起,v-for先执行,在执行v-if,通过v-if移动到容器内的元素不会重复遍历到每个值。
vue组件中的data是必须是函数。假如是对象,对象属于引用类型,那么每个组件都父用同一个数据了。如果是函数,每次函数都会创建新的数据,使每个组件的数据独立。
webpack中的babel使把es6转成es5,plugin是配置的插件,loader是解析第三方文件。
computed一个属性受多个属性影响的时候使用,watch当一条数据影响多条数据的时候使用。
csrf跨站请求伪造,诱导用户进入第三方网站,利用用户的凭证在被工资的网站执行默写操作。。避免:田间验证码。。使用token。
ddos,分布式拒绝服务,利用大量请求造成资源过载,导致服务不可用。避免。。限制单ip请求频率。
vuex
用来管理全局状态的工具,多个组件公用一套数据。便于管理
缺点:是应用级别的数据具有响应式,应用刷新数据回重置需要配合本地的存储来使用。本地的存储不具备响应式。
state:定义数据。
mutations:定义方法进行修改state中的数据但是不能进行异步操作。
actions:处理异步,可以调用mutations中的方法来修改state中的数据。
getters:根据state中的数据得到新的数据,有点类似计算属性。
module:模块化,防止随着项目过大,state中属性过多每个模块中都含有上述4个属性。
你知道虚拟dom吗?简单又谈一下?如何实现高效更新的?如何进行新旧dom树进行对比?
本质上就是一个JS对象,用来描述你希望在屏幕上看到的内容,虚拟dom可以实现高效更新,(后面如果自己能说一气说出来)。利用新旧虚拟dom树进行对比,从而进行局部进行更新。利用diff算法,主要是tree diff树对比,component diff 组件对比,element diff 元素对比
加上一些其他话术
所以虚拟dom在前端中不管是vue、react等等都采用
项目优化
进度条,移除打印,多入口main.js,cdn资源,自定义首页内容,路由懒加载,长列表优化,缓存组件
添加等待进度条,在请求拦截的时候开启NProgress.start(),在响应拦截的时候关闭。
移除发布阶段打印,先肯定是安装插件,通过环境变量process.env.NODE.env来判断是发布阶段还是开发阶段,然后移除阶段的打印。
当然还会因为开发阶段和发布阶段的代码不同,所以需要多入口的main.js。根据环境变量来判断当前所处的环境,分别使用对应环境的main.js.(vue.config.js中chainWebpack:config=>{}配置)
通过externals加载cdn资源,忽略依赖库打包,减小打包体积,通过手动引入cdn资源,就近访问所以速度块。
自定义首页内容,通过环境变量,并使用htmlwebpackplugin.option插件来显示不同环境下不同首页内容。同时也通过这个来决定是否加载cdn资料。
路由懒加载,当加载到某个路由时才加载对应的页面的资源文件
长列表性能优化,每次加载dom量过大。设置vue-virtual-scroller,来只加载可视区域的dom。
keep-alive缓存不必要组件减少请求。
项目
1,电商
主要为了对公司商城进行管理的一套后台管理系统,针对商品添加,编辑删除,分类处理,以及查看订单。
项目模块:用户管理,权限管理,商品管理,订单管理,数据统计
权限难点:给指定的角色分配权限,默认获取所有权限并渲染,但是需要更具当前角色勾选已有的权限,因为权限展示时通过element-ui的树形组件渲染的,所以要获取三级权限,利用递归循环获取3级权限id,并赋给属性组件需要的数组。
商品管理:element-ui图片上传失败,因为自己利用axios请求拦截器配置统一携带的token,但是elemnt-ui上传图片不是axios发出,所以拦截对图片上传携带token失效,我就要单独对图片上传组件进行配置请求头携带token。
添加商品时,需要将数据提交给后台,但是后台需要的商品分类数据要的是字符串1,2,3,但是我们获取到的级联选择器的是[1,2,3],此时出现冲突,但是还不能直接修改数据,因为数据为复杂数据类型,所以要对数据进行深拷贝,利用lodash对数据进行深拷贝后,然后对数据进行处理发给后端
动态路由
权限控制得来源RbAC,用户有不同得角色,不同得角色对应不同得权限。
最简单得方式,动态获取侧边栏导航(不同得角色不同得侧边栏起因是)路由规则全部生成,有弊病就是在地址访问能登进去。
路由规则动态生成,静态路由和动态路由。
动态路由,单独得模块,动态生成,在路由前置狗子获取角色权限,
利用addRoutes动态追加,退出登录重置路由,通过创建新得路由实例,将新得路由实例得matcher交给重置得matcher。404规则放在最后,动态生成得路由规则不能直接next(),next(to.path).侧边栏菜单默认绑定路由routes,这里改数据不能响应式得,将数组存到vuex,取vuex中得数据。(权限和路由名字一样,比如说什么角色有什么权限,然后路由规则又和这些权限名字一样,再类似push进去,也就是动态生成)。