前端初中高面试(含答案)

116 阅读13分钟

初级

HTML
▪ 页面导入样式时,使用link和@import有什么区别? 

link引入的样式页面加载时同时加载,@import引入的样式需等页面加载完成后再加载。 link没有兼容性问题,@import不兼容ie5以下。 link可以通过js操作DOM动态引入样式表改变样式,而@import不可以。

▪ 浏览器内多个标签页之间的通信方式有哪些 

WebSocket (可跨域)postMessage(可跨域)Worker之SharedWorker Server-Sent Events localStorage BroadcastChannel Cookies

▪ 怎么去除img之间存在的间隔缝隙?

 display:block/flex / 父级设置font-size:0

▪ 解释下为什么{} + [] === 0为true?

 {} 是空语句块而非空对象 {} + [] === 0 +[] === 0 0 === 0 true

CSS
让一个元素水平垂直居中,有多少种方法

marin/绝对定位/flex布局/已知高度:text-align:center;line-height: 元素的高度

▪ CSS盒子塌陷问题 

after伪元素 / clear / BFC

▪ ::before和::after它们的使用场景是什么? 

清浮动、三角形箭头、移动端边框1px问题

▪ 使用绝对定位position:absolute;后,就不能使用margin: 0 auto;实现居中,为什么呢?

如何解决 使用绝对定位后,脱离了文档流,相对于带有定位属性的上层定位元素定位, 解决方法定位位置用百分比。

▪ 外边距重叠是什么?

外边距重叠指的是,当两个垂直外边距相遇时,它们将形成一个外边距。 重叠后的外边距的高度等于两个发生重叠的外边距的高度中的较大者。 发生的条件: 属于同一个BFC的两个相邻元素上下margin会重叠。 

重叠的结果是什么? 

举例1:当一个元素出现在另一个元素上面时,重叠后的外边距的高度等于两个发生重叠的外边距的高度中的较大者。 举例2: 当一个元素包含在另一个元素中时(假设没有内边距或边框把外边距分隔开),它们的上和/或下外边距也会发生重叠。如果这个外边距遇到另一个元素的外边距,它还会发生重叠。

 怎么防止外边距重叠?

 浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠(注意这里指的是上下相邻的元素) 外层元素padding代替 内层元素透明边框 border:1px solid transparent; 用同一方向的margin,都设置为top或者bottom。

▪ css中的border:none和border:0px有什么区别

 在于浏览器解析与否 border为0的情况下虽然看不见,但是浏览器会对border进行渲染,还是占据内存的 而border为none时浏览器不会对其渲染,所以不会占据内存 border为none的兼容差 在老IE浏览器上还是会有边框 而border为0的时候是可以隐藏的

VUE
▪ methods、watch、computed区别 

1、method: 只要发生重新渲染,method 调用总会执行该函数 无缓存 

2、计算属性是基于他们的依赖进行缓存的。只有在相关依赖发生改变时,它们才会重新求值。 有缓存 

3、Watch是一个侦听的动作,用来观察和响应Vue实例上的数据变动 watch则主要用于观测某个值的变化去完成一段开销较大的复杂业务逻辑

组件传值有哪些方法

Emit、props、vuex、

eventBus

provide/inject

parent/parent/children

$attrs/listeners

▪ vue给组件绑定自定义事件无效怎么解决 

1、组件外部加修饰符.navtive 

2、组件内部声明$emit('自定义事件')

▪ vue怎么实现强制刷新组件?

1. 如果要在组件内部中进行强制刷新 调用this.$forceUpdate()强制重新渲染组件 

2. 如果是刷新某个子组件 利用v-if指令的特性 当组件的key 值变更时,会自动的重新渲染

▪ 请描述下vue的生命周期

生命周期就是vue从开始创建到销毁的过程,分为四大步(创建,挂载,更新,销毁),每一步又分为两小步,如beforeCreate,created。beforeCreate前,也就是new Vue的时候会初始化事件和生命周期;beforeCreate和created之间会挂载Data,绑定事件;接下来会根据el挂载页面元素,如果没有设置el则生命周期结束,直到手动挂载;el挂载结束后,根据templete/outerHTML(el)渲染页面;在beforeMount前虚拟DOM已经创建完成;之后在mounted前,将vm.$el替换掉页面元素el;mounted将虚拟dom挂载到真实页面(此时页面已经全部渲染完成);之后发生数据变化时触发beforeUpdate和updated进行一些操作;最后主动调用销毁函数或者组件自动销毁时beforeDestroy,手动撤销监听事件,计时器等;destroyed时仅存在Dom节点,其他所有东西已自动销毁。这就是我所理解的vue的一个完整的生命周期;

▪ 说说你对keep-alive的理解是什么? 

保留组件状态 避免重新渲染

▪ 删除数组用delete和Vue.delete有什么区别?

delete:只是被删除数组成员变为 empty / undefined,其他元素键值不变 Vue.delete:直接删了数组成员,并改变了数组的键值(对象是响应式的,确保删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限制)

JavaScript
JS原始数据类型有哪些?引用数据类型有哪些?

原始类型(boolean,null,undefined,number,string,symbol)

引用类型:对象Object(Object,Array,RegExp,Date,Math,Function)

简述一下 == 和 === 的区别

==两边类型不同,比较时会进行隐式转换,再比较

===两边的量的值与量的类型和值必须完全相同

谈谈你对闭包的理解

当访问一个变量时,解释器会首先在当前作用域查找标识符,如果没找到,就去父作用域找,直到找到该变量的标识符或者不在父作用域中,这就是作用域链。每个子函数都会拷贝上级的作用域,形成一个作用域的链条。

本质:当前环境中存在指向父级作用域的引用。

场景:返回一个函数;作为函数参数传递;定时器,事件监听,Ajax请求,跨窗口通信,Web Workers或者任何异步中,只要使用了回调函数,实际上就是使用了闭包。

IIFE(立即执行函数表达式)创建闭包,保存了全局作用域window和当前函数的作用域,因此可以全局变量。

箭头函数与普通函数的区别

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误

不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替

不可以使用yield命令,因此箭头函数不能用作Generator函数

实现深浅拷贝

浅拷贝:

仅拷贝第一层

Object.assign,展开运算符 ... 等可实现浅拷贝

深拷贝:

JSON.parse(JSON.stringify(object))

缺点:

会忽略 undefined

会忽略 symbol

不能序列化函数

不能解决循环引用的对象

中级

JavaScript
事件委托、事件冒泡、事件捕获
简述数组中的高阶函数map,filter,reduce方法

map:

接受两个参数,一个是回调函数,一个是回调函数的this值(可选);

创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果,对原来数组没有影响。

filter:

一个函数参数。这个函数接受一个默认参数,就是当前元素。这个作为参数的函数返回值为一个布尔类型,决定元素是否保留。

reduce:

接收两个参数,一个为回调函数,另一个为初始值。回调函数中三个默认参数,依次为积累值、当前值、整个数组。

▪ 说说你对javascript的作用域的理解 

1、全局作用域:就是在顶层环境中申明的变量都是全局作用域,他们的属性其实都在window对象下面。 2、函数作用域:在函数内部定义的变量都是函数作用域,只能在函数中访问到,当然也可以通过闭包来访问。除此之外,在其他地方是没法访问函数内部的变量的。 

2、局部作用域:es6中新增的特性,弥补了以前只能使用匿名及时运行函数来创建局部变量的缺陷。使用很简单,直接用let来申明变量就行。也可以使用const来申明变量 4、作用域链:先从函数内部作用域找,如果没有找到就从函数的父作用域找,一直到顶层作用域。

▪ js中判断是否为一个函数

 function isFunction(fn) { return Object.prototype.toString.call(fn)=== '[object Function]'; }

▪ Promise是什么、Promise.all和Promise.race区别

1、Promise是异步编程的一种解决方案,比传统的回调函数和事件更合理和强大。 它有三种状态: Pending 初始态; Fulfilled 成功态; Rejected 失败态 

2、promise.all 是数组里面所有的 promise对象执行结束之后 会返回一个 存储所有 promise对象的结果 promise.race 返回执行速度最快的promise对象返回结果

▪ 点击一个input、依次触发哪些事件

 移入-按下-获取焦点-弹起; onmouseenter→onmousedown→onfocus→onmouseup;

▪ 请描述你对浏览器同源策略的理解

同源策略是指,某个页面上执行的 AJAX/Fetch 请求只能访问到同域名下的 URL。 这是出于安全性考虑,然而在某些需要跨域的场景中,通过在服务端设置 CORS 响应头 Access-Control-Allow-Origin(允许的来源域名)、Access-Control-Allow-Method(允许的 HTTP Method)等,可以响应来自其他域的请求。

VUE
▪ 你认为vue的核心是什么

1、数据驱动 专注于View 层。它让开发者省去了操作DOM的过程,只需要改变数据。 

2、组件响应原理 数据(model)改变驱动视图(view)自动更新 

3、组件化 扩展HTML元素,封装可重用的代码。

▪ SPA首屏加载速度慢的怎么解决?

1. 通过Gzip压缩 

2. 使用路由懒加载 

3. 利用webpack中的externals这个属性把打包后不需要打包的库文件都分离出去,减小项目打包后的大小 

4. 使用SSR渲染

▪ route和router有什么区别

route:代表当前路由信息对象,可以获取到当前路由的信息参数 router:代表路由实例的对象,包含了路由的跳转方法,钩子函数等

▪ 说说vue-router完整的导航解析流程是什么 

1. 导航被触发; 

2. 在即将离开的组件里调用beforeRouteLeave守卫; 

3. 调用全局beforeEach守卫; 

4. 在复用组件里调用beforeRouteUpdate守卫; 

5. 调用路由配置里的beforeEnter守卫; 

6. 解析异步路由组件; 

7. 在被激活的组件里调用beforeRouteEnter守卫; 

8. 调用全局beforeResolve守卫;

9. 导航被确认;

10. 调用全局的afterEach钩子; 

11. DOM更新

12. 用创建好的实例调用beforeRouteEnter守卫中传给next的回调函数。

▪ vue-router路由有几种模式?说说它们的区别?

 hash模式: 1.url路径会出现“#”号字符 2.hash值不包括在Http请求中,它是交由前端路由处理,所以改变hash值时不会刷新页面,也不会向服务器发送请求 3.hash值的改变会触发hashchange事件 history模式: 1.整个地址重新加载,可以保存历史记录,方便前进后退 2.依赖H5 API和后台配置,没有后台配置的话,页面刷新时会出现404

Vue.nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

异步更新队列,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。这样回调函数将在 DOM 更新完成后被调用.

谈谈对keep-alive的了解

keep-alive 可以实现组件的缓存,当组件切换时不会对当前组件进行卸载。常用的2个属性 include/exclude ,2个生命周期 activated , deactivated

Vuex action 与 mutation 的区别

mutation 是同步更新, $watch 严格模式下会报错

action 是异步操作,可以获取数据后调用 mutation 提交最终数据

高级

VUE
▪ 简述Vue中diff算法原理

1、先同级比较、再比较子节点 

2、先判断一方有儿子一方没儿子的情况 

3、比较有没有儿子的情况 

4、递归比较子节点

▪ Vue模板编译原理 

模板引擎实现原理 通过 with 可以帮我们解决作用域的问题 包起来 并且通过new Function来实现 AST只能表现出HTML语法

▪ 说说你对单向数据流和双向数据流的理解

 单向数据流:所有状态的改变可记录、可跟踪,源头易追溯;所有数据只有一份,组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于应用的可维护性;一旦数据变化,就去更新页面(data-页面),但是没有(页面-data);如果用户在页面上做了变动,那么就手动收集起来(双向是自动),合并到原有的数据中。 双向数据流:无论数据改变,或是用户操作,都能带来互相的变动,自动更新。

▪ 说说你对Object.defineProperty的理解

 vue的数据双向绑定的原理就是用的Object.defineProperty这个方法,里面定义了setter和getter方法,通过观察者模式(发布订阅模式)来监听数据的变化,从而做相应的逻辑处理。

▪ 说说你使用vue过程中遇到的问题(坑)有哪些,你是怎么解决的?
▪ Vue 常见性能优化方式 

合理使用v-show 和 v-if 合理使用computed v-for 时要加key,以及避免和 v-if 同时使用 自定义事件、DOM 事件及时销毁 合理使用异步组件 合理使用keep-alive data层级不要太深(因为深度监听一次性监听到底) 使用 vue-loader 在开发环境做模板编译(预编译) webpack层面的优化。 

▪ 前端通用的性能优化,如果图片懒加载 使用 SSR

HTTP
▪ 为什么连接的时候是三次握手,关闭的时候却是四次握手?

 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

JavaScript
▪ js延迟加载的方式有哪些?

 defer 属性 async 属性 动态创建DOM方式 使用jQuery的getScript方法 使用setTimeout延迟方法 让JS最后加载