2021中级前端面试总结

558 阅读12分钟

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

跨域

  1. jsonp(利用script标签没有跨域限制的漏洞实现。缺点:只支持GET请求)
  2. CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)
  3. Node中间件代理
  4. 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进去,也就是动态生成)。