经过一周多的紧张面试,目前在武汉一家公司进行前端开发工作,分享一下这段时间以来面试提到的问题;希望能够帮助到大家。
一、CSS方面
1.css水平垂直居中的方式?
1.子绝父相,子盒子(top left right bottom都为0,margin:auto)
2.子绝父相, 子盒子(transform:translate(-50%,-50%)) left和top走一半
3.子绝父相,子盒子(top/left各50%,margin-left和margin-top走负的一半)
4.display:flex align-items:center justify-content:center
2.如何实现左边固定200px宽度,右边自适应的布局?
1.给定左边200px的宽度 calc(宽度-200px)
2.flex布局(左边固定,右边自适应)
3. css3新增特性有哪些?
动画(过渡动画、帧动画) 弹性布局、媒体查询、渐变(background:linear-gradinent)
4.css实现0.5px的线
transform: scaleY(.5);
二、HTML方面
1.什么是标签语义化?
语义化的标签,旨在让标签有自己的含义。比如说:p标签的含义是段落,hn是分级标题,而span就无特殊含义。
2.BFC是什么?
块级格式化上下文,可以把BFC理解为一个封闭的区域,盒子内部的元素无论怎么样,是跑,是跳、还是飞,都不影响到外部。以下几种情况会触发BFC特性的情况:
position:absolute、fixed
display:inline-block table-cell
3.清除浮动的方法有哪些?
1.父级div定义height 最后一个浮动元素后加空div标签 并添加样式clear:both
2.父标签添加样式overflow为hidden/auto
4.子绝父相是根据什么来定的?
相对定位是相对于自身定位的
绝对定位是绝对浏览器
5.重绘和回流
重绘就是修改样式(修改颜色或背景色)
回流:元素的大小或者位置发生改变(当页面布局发生改变的时候),触发了重新布局导致渲染树重新计算布局和渲染
重绘不一定会造成回流,回流一定会造成重绘
JavaScript面试题
1.JavaScript的数据类型有哪些?
基本数据类型:Number String Boolean NAN Undefinde symbol(es6新增 表示唯一性)
复杂数据类型: Object注:这里如果说了symbol就需要解释它的意思以及用处
2.数据类型检测的方式有哪些?
typeof(数组、对象、null都会被判断为Object 其他判断都正确) instanceof(只能判断引用数据类型) Object.prototype.toString()
3.面向过程和面向对象的区别?
面向过程就是分析问题的步骤(把大象装到冰箱的问题)
面向对象是以功能来划分,而不是步骤,是抽取某一类事物共同的属性,将共同的属性和行为按功能集合。
4.什么是深拷贝和浅拷贝?如何实现?
浅拷贝拷贝的是地址,当我对数据进行改变时,原来的数据也会被改变
深拷贝是重新开辟了空间,改变数据对原来的数据没有任何的影响
如何实现:
1.使用cloneNode(false || 不填) 的时候是浅拷贝
2.使用cloneNode(true) 是深拷贝
3.深拷贝前先看当前要拷贝的数据是否为对象类型,如果是 则直接把数据使用JSON.stringify()转为JSON字符串,如果不是对象类型,先使用JSON.parse()转js对象,再使用JSON.stringify转为JSON字符串
4.使用递归实现深拷贝:
定义一个函数接收新旧对象,然后遍历旧对象,然后for key in 判断是不是数组、然后看是不是对象、最后判断是不是简单数据类型,
每一次判断结束之后 把判断得到的旧数据给新对象。
5.什么是闭包?大量使用闭包的缺点?
闭包指的是在函数内部能够调用外部的变量,闭包的作用使函数的作用域扩大。
缺点:使用不当会造成内存泄漏。
如何避免内存泄漏: null方法和函数内部使用let关键字。
为什么会造成内存泄漏:代码执行完成之后 存在声明后没使用的全局变量,这样一直堆积 未被释放 就会造成内存空间不够 导致内存泄漏。
闭包的应用场景 原型链的使用场景
闭包就是回调函数,然后节流防抖会用到。
6.谈一下你对继承的理解:
1.原型链继承
优点:可以访问父类的属性和方法和原型上的属性和方法;
缺点:继承如果是引用类型,其中一个子类进行修改,全部都会受到影响,造成实例共享;
2.构造函数实现继承
优点:可以保证每个子类维护自己的属性;
缺点:无妨访问原型链上的属性和方法;
3.组合继承
优点:既可以访问原型上的属性和方法,又可以每个子类维护自己属性;
缺点:每次创建一个子类实例,父类都会被执行一次;
7. es6常用语法有哪些?
set(去重) 箭头函数 拓展运算符 数组解构 模板字符串 promise async/await
8.数组去重的方法有哪些?
因为一般都是说思路 所以这里不写代码演示
使用for循环嵌套+ splice去重
使用indexof 判断新数组中有没有这个数据,如果没有再push到这个新数组中
set方法
9.箭头函数和普通函数的区别?
首先箭头函数没有自己的 this,当在内部使用了this时,它会指向最近一层作用域内的 this,普通函数遵循谁调用指向谁,否则就指向全局。
构造函数(Constructor)中的this指向调用该构造函数所创建的实例对象。
10.AddEventlistener和原生的onclick的区别?
这题当时有点懵 没反应过来🤣
区别就是 前者可以给一个事件上绑定多个事件,后者不能。
前者的第三个参数是一个布尔值,指定是使用事件冒泡还是事件捕获。此参数是可选的。
11.null和undefined的相同点和不同点?
相同点:非严格模式下相等
不同点:typeof运算符处理Null类型值返回object,Undefined类型值返回undefined。
12. 谈一下对promise的理解
//Promise有三种状态: pending(进行中)、fulfilled(已成功)、rejected(已失败)
直白来说 promise是一个对象,它是解决异步操作的一种方法,promise接收的是一个函数,函数接收两个参数(reslove和reject),分别对应成功和失败
同时promise本身有两个方法 .then和.catch 对应成功后的调用和失败的调用,promise的链式编程思想可以解决地域回调的问题
promise的缺点:
1.一旦新建就会立即执行,无法中途取消
2.当处于pending状态时,无法得知当前处于哪一个状态,是刚开始还是刚结束
13.async/await
async可以让函数内部的代码都像同步一样执行,但是需要在异步代码的前面添加await
14.节流和防抖
这个当时是问我有没有做过优化 我回答的是一个防抖操作,具体点就是嗯... 淘宝输入商品后 按照最后一次输入的内容来请求商品数据进行调用,减少了发送请求的频率。
都能够减少事件触发的频率
节流就是水龙头滴水事件 --- 一段时间执行一次事件
防抖是只执行最后一次触发的事件
15. 什么是地域回调?怎么解决?
一个异步请求套着一个异步请求,一个异步请求依赖于另一个的执行结果,使用回调的方式相互嵌套
由多层嵌套的回调函数组成的代码称为回调地域
如何解决地狱回调的问题?
1.Promise的链式编程可以保证代码的执行顺序,前提是每一次在then做完处理后,一定要return一个Promise对象,这样才能在下一次then时接收到数据。
2.async/await
16.new操作符做的那几步?
进行以下4步:
1.创建一个空的obj
2. this指向这个新对象
3.为这个新对象添加属性和方法
4.返回新对象
17.谈一下你对JS执行机制的理解
JS执行代码分为同步任务和异步任务两种,同步任务优先在主线程上执行,异步任务会先放到任务队列中,等主线程任务执行完毕之后再从任务队列中读取任务执行。异步任务分为宏任务和微任务,先执行宏任务执行完毕之后 看有没有微任务未被执行 如果有,就优先执行
微任务 然后再执行下一次的宏任务;而从任务队列拿异步任务的过程到执行栈中的过程是不间断的,这个过程也称为事件循环。
宏任务有:setTimeout setInterval ajax
微任务有:promise async/await
VUE面试题
1.vue响应式原理
Vue实例创建时,会遍历data中的属性,用Object.defineProperty()转为getter/setting
2. data为什么不能是引用数据类型?
这个题变相是问 为什么data是函数而不是对象
答:对象是引用类型,多个实例引用同一个对象时,只要一个实例对这个对象进行操作,那么其他实例中的数据也会发生变化。所以不能是对象。
3.v-if和v-for哪个先执行?
v-for的优先级比v-if更高,这意味着 v-if将分别重复运行于每个 v-for循环中。
4. computed和methods中方法的区别?
computed有缓存的效果,computed和methods第一次执行方法,computed会把结果缓存下来,二次执行的时候 computed里面的该函数就不会执行,而methods里面的函数会再次执行。
5. computed和watch适合分别在什么时候使用?
computed:当多个条件影响一个结果的时候 使用computed
watch: 一个条件影响多个
6.vue的生命周期有哪些?以及每个函数做的事情
答:创建 挂载 更新 销毁 激活
1.创建前:beforeCreate (❤)
给实例化的Vue对象添加了属性和方法还有生命周期函数。
2.创建后:created (应用场景:发送网络请求获取数据) (❤❤❤❤❤)
把methods和data添加到Vue实例化对象上,所以在created周期内可以访问data和methods中的数据
3.挂载前:beforeMount(❤)
在DOM挂载页面进行data数据预处理
4.挂载后:mounted(❤❤❤❤❤)
已经把DOM挂载到页面上了,是可以进行DOM元素操作的阶段了(可以理解为已经将虚拟DOM绘制到浏览器中------即为真实DOM)
更新:data数据发生变化才会触发
5.更新前: beforeUpdate(❤)
数据进行变更,DOM没有实际更新前
6.更新后 :updated(❤❤❤)
数据更新的DOM也已经产生在页面上了,可以继续访问
销毁:页面DOM元素进行移除
7.销毁前:beforeDestroy(❤❤)
通常进行事件的解绑,定时器,计时器的销毁
8.销毁后 destroyed
所有vue实例和DOM元素就全部销毁
9.激活时 activated
是在有用keep-alive的时候组件被缓存激活时触发
10.失去激活 deactivated
是在keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用
11.errorCaptured
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生
错误的组件实例以及一个包含错误来源信息的字符串,此钩子可以返回 false 以阻止该错误继续向上传播
7.请描述一下keep-alive的使用场景
keep-alive是vue的内置组件,当它动态包裹组件时,会缓存不活动的组件实例,它本身不会渲染成一个DOM元素,也不会出现在父组件链中。
作用:就是在组件切换工程中将状态保留在内存中,减少加载时间以及性能消耗,提高用户体验。
使用的优点:保存组件不会被销毁(看到一半 跳转到另一个页面,再回去的时候页面还是会存在到原来的位置上),性能会好点。
8.路由传参的方式有哪些?
路由传参的方式有哪些?
两种传参方式:params传参和query传参,其中params传参又分为在url中显示参数和不显示参数两种方式。
区别:
params用name引入,query用path引入,接收的参数都是类似的,分别是this.$router.params.name / this.$router.query.name
安全性问题: params类似于post query类似get,params传值相对更安全点, query通过url传参,刷新后页面还在,params刷新页面不在了。
9.如何实现路由懒加载?
1.component: resolve => require(['放入需要加载的路由地址'], resolve)
2.import 直接将组件引入的方式 也是官方提倡的
10.vue的路由钩子函数有哪些?
分为全局钩子函数和单个钩子函数、组件内的路由钩子函数
全局:beforeEach、afterEach
路由前置守卫:beforeEach(to,form,next)
应用场景:可进行一些页面跳转前处理,例如判断需要登录的页面进行拦截,做登录跳转!!管理员权限判断、浏览器判断
路由全局后置守卫: afterEach 是页面加载之后
单个: beforeEnter
组件内的:beforeRouteEnter、beforeRouteLeave、 beforeRouteUpdate
11.怎么使用vue的过滤器?过滤器只能在插值表达式中使用吗?
分为全局和局部两种
全局过滤器:在main.js导入filter.js文件
参数一:过滤器名字(也就是管道符后面的处理函数)
参数二:处理函数,处理函数的参数同上
Vue.filter( filterName,( )=>{ return // 数据处理结果 } )
局部过滤器:filters里面写处理函数
过滤器使用场景:双花括号插值 或 v-bind表达式。
12.vue双向绑定原理是什么?
通过数据劫持(object.defineProperty)和观察者模式(当属新发生改变的时候,使用改数据的地方也发生改变)来是实现的。
13.v-model的原理是什么?
v-bind绑定value,v-on绑定input事件
14. 为什么更新了数据却不能操作dom?如何解决?
因为数据更新是同步的,视图更新是异步的,所以刚修改完数据dom是不会立刻更新的,如果想操作dom,需要将操作dom的方法放到$nextTick中,进行异步处理。
15.v-for后面为什么要加:key?
key是唯一标识符
设置key值是为了提高动态加载的效率,为了提高虚拟DOM的效率,规定需要设置key值,同时dom diff算法也会根据有无key值进行比对。
16.vue中组件通信的方式有哪些?
父子组件传值:{
父传子---- 子组件使用props接收
子传父---- 子组件使用$emit+事件,父组件定义接收事件名 并在父组件methods中定义函数
}
组件中可以使用$parent和$children获取到父组件实例和子组件实例
使用Vuex进行状态管理
使用eventsBus 进行跨组件触发事件,EventBus.$emit()发 EventBus.$on收
$attrs和$listeners(爷孙)
$refs
indexDB
localStorage
17.什么是插槽?什么是具名插槽?什么是作用域插槽?什么是具名作用域插槽?
插槽类似与占位符,具名插槽是指在特定的位置显示相对应的内容,v-slot:xxx xxx对应的是组件内的slot的name属性对应的,也就是插槽的名称。
作用域插槽主要是在书写插槽内容时可以获取到插槽作用域的值
一句话概括就是: v-slot后面是插槽的名称 = 后边是组件内部绑定作用域的映射。
18.如何优化Vue性能
1.组件懒加载
2.不要将所有的数据都放到data中
3.v-if和v-for不在一起使用
19.vuex的5种状态
state:定义数据状态
actions:异步处理(修改)数据状态
getters:用来返回state加工后的数据,类似vue的过滤器和计算属性
mutations:同步处理(修改)数据状态
module:存放各个模块
20.webpack优化方式
这个问题两年工作经验的朋友可能会遇到哦
1.DLL方式,指定包在的项目中,build的时候不在打包对应的包,使用的时候引入。
2.增强代码代码压缩工具,推荐采用 webpack-parallel-uglify-plugin 插件
用 Happypack 来加速代码构建
21.会给一个需求让谈谈如何实现组件封装
首先组件封装就代表复用性强,所以我们可以在拿到设计图之后 看看哪些位置需要封装组件。就比如说我们封装一个固定的头部,需要把它放在component文件夹下 然后根据需要看是否要注册全局组件去使用。
项目方面
嗯 我这边的建议是面试之前有项目的小伙伴多熟悉一下自己的项目,面试官会问到项目中的重点,比如说登录、路由、用户权限...问题,一定要多看看 熟悉自己的代码。没有项目的小伙伴可以写自己平时做练习时候的项目 然后归纳总结讲清楚就可以啦。