前端简单面试题

292 阅读15分钟

图片懒加载的原理

主要是判断当前图片是否到了可视区域这一核心逻辑实现的

  1. 拿到所有图片的dome

  2. 遍历每个图片判断当前是否到了可视范围内

  3. 如果到了就设置图片的src属性

  4. 绑定window 的scroll 时间 对其进行事件监听

作用:

  1. 减少资源加载 页面启动只加载首屏的图片 可以减少浏览器的负担

  2. 防止并发加载的资源过多而阻塞js的加载

  3. 能提升用户体验

js数组和对象的区别:

数组的数据没有”名称”(name),对象的数据有”名称”(name)

节抖和防流原理:

节流:不管事件触发的有多频繁 都会保证在规定时间内一定会执行一次

防抖:只在最后一次事件后触发一次函数

Vue组件通讯:

  1. 父传子 props:

父组件通过import引入子组件,并注册,在子组件中添加你要传递的属性 子组件通过props接收 接收有两种形式 一种通过数组接收  只是简单的接收 一种是对象形式接收 可以设置要传递的数据类型和默认值

  1. 子传父 $emit:

子组件通过绑定事件触发函数 设置this.$emit() 他有两个参数 一个是要派发的自定义事件 二是要传递的值 在父组件中通过@这个自定义组件 在methods中触发事件获取默认值

  1. 兄弟和兄弟:event bus和vuex

event bus :

就是创建一个空的vue作为一个公共的bus 在两个兄弟组件分别引入bus 组件A通过bus.emit发送数据,组件B通过bus.emit发送数据,组件B通过bus.on接收数据

vuex:

vue是一个状态管理工具  主要解决大中型复杂项目的数据共享问题 主要包括state,actions,mutations,getters和modules 5个要素 主要流程:组件通过dispatch到actions。actions是一个异步操作 在actions通过commit到mutations,mutations通过逻辑改变state 从而同步到组件 更新数据状态 

解决跨域的方案:

  1. jsonp:

利用动态创建script标签请求后端接口地址 然后传递callback参数 后端接收callback 后端通过数据处理 返回callback函数调用的形式 callback中的参数就是json

  1. 代理的方式(前端代理后端代理):

前端代理在vue中使用vue.config.js里面配置一个proxy 里面有个target属性指向跨域链接 修改完重启项目就可以了,实际上就是启动一个代理服务器 绕开同源策略 在请求的时候 通过代理服务器获取到数据再转给浏览器

  1. CORS:

cors全称叫跨域资源共享 主要是后台工程师设置后端代码来达到前端跨域请求

Promise在项目中的实际使用

promise封装了axios请求 抛出了post get put delete方法,里面return一个promise实例

请求成功后 将结果传递给resolve() 使用时 结合async await使用

promise是同步执行 then方法是异步执行

Promise的优点和缺点:

优点:解决回调地狱问题   更好地进行错误捕获

缺点:

  1. 无法取消Promise 一旦新建它就会立即执行 无法中途取消

  2. 如果不设置回调函数 Promise内部抛出错误 不会反应到外部

  3. 当处于pending状态时 无法得知目前进展到哪一个阶段

### async await用法

使代码以同步的方式的写法完成异步操作

async 表示函数里面有异步操作

await 表示紧跟再后面的表达式需要等待结果

同源策略是什么:

就是指协议+域名+端口三者相同 即便两个不同的域名指向同一个ip地址 也非同源 他是浏览器最核心也最基本的安全功能

ES6新增特性:

let/const  箭头函数 模板字符串 解构赋值 模块的导入和导出 Promise

let const区别

相同点:

1.  只在块级作用域内有效

2.  同时存在暂时性死区

3.  不可重复声明

不同点:

  1. let声明的变量可以改变而const声明的常量不可改变  const声明之后必须赋值

var与let的区别:

  1. 作用域 2.重复声明 3.绑定全局对象 4.变量提升与暂存死区

var的作用域是全局 let的作用域当前所处的代码块

var可以重复声明    let不可以重复声明

var会在全局对象里新建一个属性   let不会再全局对象新建属性

var声明变量存在变量提升   let 声明变量存在暂时性死区

微任务和宏任务

先宏后微

宏任务 setTimeout  setInterval

微任务 promise.then.catch

nextTick的作用

vue中的nextTick主要用于处理数据动态变化,DOM还未及时更新的问题,

用nextTick就可以获取数据更新后最新DOM的变化

$nextTick

就是用来知道什么时候 DOM 更新完成的

适用场景:

  1. 根据数据动态为dom元素添加事件 如果dom没有渲染完毕 添加不了事件就会用到

  2. 在使用第三方插件 dom发生变化时 需要nexttick回调函数重新执行应用插件的方法

  3. 数据改变后获取焦点

vue异步更新队列

Vue在观察到数据变化时并不是直接更新DOM,而是开启一个队列,并缓冲在同一个事件循环中发生的,所以数据改变,在缓冲时会去除重复数据,从而避免不必要的计算和DOM操作,然后,在下一个事件tick中,Vue刷新队列并执行实际工作

v-for和v-if的优先级

v-for的优先级比v-if高

keep-alive组件的作用

主要用于保留组件状态或避免重新渲染

属性:

include:字符串或正则表达式 只有匹配的组件会被缓存

exclude:字符串或正则表达式 任何匹配的组件都不会被缓存

用法:

包裹动态组件 会缓存不活动的组件实例 而不是销毁他们

VUE中的动态组件

VUE里的内置标签component,他可以配合本身is属性来进行动态组件的渲染,就是is属性的值可以是一个变量,是哪一个组件的名字就去加载对应的组件

### Vue中的动态侧边栏路由如何实现的:

后端发挥一个token值 然后我拿着token值中导航守卫里面 去请求了一个动态路由表 因为后端返回的动态路由表是一个路由字符串,无法解析,然后递归遍历一下,把里面的字符串类型的组件地址,变成了一个箭头函数方式引入的,因为有子路由,所以只能递归处理,其实就是把后端返回的基础路由表里面去,这样渲染出来的路由,及时一个动态的 可以被控制的

项目中的按钮权限是如何来进行控制的

在项目中创建了一个directives文件夹,在里面创建一个vue.directive创建一个控制按钮是否显示的命令,在登录的时候,后端会通过接口返回一个,当前用户具有所有按钮的权限标识数组  把自定义指令定义在每一个按钮上,传上一个当前按钮的权限标识,然后指令中inserted钩子函数里面,来判断这个权限标识是否中后端返回的标识数组中,如果在 操作按钮正常展示 不在就隐藏

说一下对MVVM的理解

主流的框架都是MVVM模式  比如 我项目中经常用的vue

MVVM框架里面M的话就是数据层 V就是View视图层 中间通过一个Viewmode进行双向绑定,能进行dom监听和数据绑定,里面是通过Object.defineProperty对当前组件中data的所有属性添加了get和set方法 这就形成了数据驱动视图 视图层和数据层就相互分离,便于维护,只要修改了数据层视图层就发生变化,如果不变的,可以使用this.$set方法来进行

css3新增特性有哪些

c3和c2多了好多针对移动端的特性 比如:border-radius圆角、box-shadow盒阴影、transition过度、transform实现位移 倾斜 旋转 绽放、animation关键帧动画

新增选择器:nth-child选择器 以及 flex弹性盒子

实现div垂直居中

第一种:定位

  1. 给div设置绝对定位 left、right、bottom、top设置为0 margin:auto水平垂直居中

  2. 给div设置绝对定位 left为50% top为50% 给div设置距左是自身的一半 margin-left:自身宽度/2 margin-top:自身高度/2

  3. 给div设置绝对定位 left为50% top为50% 再给div设置跨左和跟上是自身的一半 transform:tarnslate3d (-50%,-50%,0 )

第二种:flex布局

  1. 一个父级div和一个子级div 给父级div设置display:flex 并且设置父级div的水平居中justify-content:center  并且给父级div设置垂直居中 algin-items:center

clearfix解决什么问题 或 div塌陷问题

主要是给父元素有高度

方法一:给父级元素设置绝对定位 position:absolute

方法二:给父级元素设置 overflow:hidden

方法三:通过伪对象来实现

clearfix:after{

   content:' '

   display:block

   clear:both

   height:0

}

什么是(BFC)

把一个盒子设置为bfc之后 里面的变化不会影响外面的变化 用它可以解决一些布局方面的问题

比如 margin重叠 高度塌陷

盒模型的理解( IE和W3c标准盒模型 ):

盒模型就是浏览器把一个个标签都看一个形象中的盒子,每个盒子都会有内容,边框以及内容和边框中间的缝隙,还有盒子与盒子之间的外间距

IE盒模型:设置的width宽度+margin的值 其中 width值包含了padding和border

标准盒模型:width+padding+border+margin

IE和标准宽度之间切换通过 box-sizing:border-box设置成content-box来切换

css3动画

  1. 过度动画:通过transition来实现 设置过度的属性 运行时间和延迟时间
  2. 关键帧动画:通过animation配合keyframes实现

transition和animation有两点区别:

  1. transition需要事件来触发 animation不需要

  2. transition只要开始和结束两种状态  animation可以多种状态 并且可以循环次数

rem和em的区别:

rem和em都是相对单位  他们的标签不同

rem:相对于跟字号

em:相对于父元素标签的字号

手机端如何做适配

手机端的适配没有最好的方法,目前前端适配的方法有 百分比 媒体查询 flex布局 em rem vw vh

vw和vh了解吗

vw和vh是一个css布局单位 

vw和vh分别是相对于屏幕宽度和屏幕高度 1vw相当于屏幕宽度的1% 100vh相当于屏幕高度的100%

你平时怎么写 css(或者说佻用过 css 预处理器吗,用过 Less 和 SASS 吗?)

平时的话用less写css 他可以定义变量 嵌套等功能 sass和less都是css的预处理器 方便开发人员写css

cookie,localStorage和sessionStorage的区别

cookie 可以设置失效时间 他没有自己的存取方法 localStorage和sessionStorage有自己的存取方法

cookie关闭浏览器后失效 locationStorage除非被清除 否则永久保存  sessionStorage关闭页面或浏览器清除

cookie 存放数据的大小 4k左右  localStorage和sessionStorage是 5MB

IE8 如何支持语义化标签

引入html5shiv.js库就ok 他可以吧语义化标签在低版本浏览器转换块元素 让浏览器解析

常用算法相关:

排序 去重 地址栏解析对象 深拷贝 浅拷贝

  1. 数组排序:冒泡排序:随便从数组中那一位数和后一位比较 

           想从小到大排序  就把小的放前面 反复进行交换位置就是排序

  1. 数组去重:1. 利用Es6set来实现 2. 借用临时对象的方式

  2. 地址栏解析成对象

自我成长相关:

平时怎么学习新技术的?

  1. 上官网看文档 

  2.  上知乎

  3. 通过专业的书籍系统学习

未来的职业规划是什么?

2年内先做好项目

虚拟dom的理解:

大致说一下我对虚拟dom的理解 正是 virtual(喂车额奥) DOM 这一个特性 能够性能更高 

虚拟DOM 就是提前使用js的方式表示Dom结构树来 存储到内存中 同样的方式 最终只会执行一次 大大提高了性能

object.defineproperty 的属性:

configurable enumerable value writable get set

                         因奶m播

深拷贝、浅拷贝:

他是经常操作复杂数据类型,当我们对一个数据拷贝出一个副本 去修改这个副本

如果原数据没有改变的话 就是深拷贝

如果原数据改变的话 就是浅拷贝

这里有一个堆和栈的问题 引用数据类型是存到堆内存里面的 保存的是一个内存地址的指针指向

浅拷贝就是指针指向相同 所以会发生改变

深拷贝就是开辟了一个新的空间 重新在堆内存里 不会互相影响

Vue常用的修饰符:

v-on指令修饰符:

.stop:禁止事件冒泡

.prevent:阻止事件冒泡

.keyCode:特定键触发

.native:监听组件根元素

.once:只触发一次回调

.left:鼠标左键触发

.right:鼠标右键触发

.middle:鼠标中键触发

为什么data要return一个对象:

因为一个组件是可以共享的 他们的data是私有的 所以每个组件要return一个新的data对象 

返回一个唯一的对象 不要和其他组件共用一个对象

v-if和v-show的区别:

他们都是可以隐藏和显示一个元素

v-if是惰性的 他的值为false的时候 不会加载对应的元素 为true的时候会动态的加载对应的元素

v-show 无论为true还是false 都会加载对应的html代码 值为false 用display:none隐藏元素 为true 用display:block显示元素

EventLoop 事件循环机制:

是js底层的运行原理  js是单线程的 如果有耗时的任务就会影响执行效率

代码都在主线程中执行 当遇见ajax请求和setTimeout定时器的时候 会开始一个异步线程

异步线程耗时之后会推入一个异步队列等待执行

当主线程执行完毕会到异步队列取出一个执行 再去取第二个 来回取的过程叫做事件循环机制

Vue和Jquey的区别

Jquey是操作DOM的神器 它封装很多好用的dom操作和怎么获取ajax 比如$.ajax()

Vue的作用是数据驱动和组件化 不怎么操作dom 可以用ref来操作dom或组件

权限:

前端做权限需要后端配合

按钮权限  路由菜单权限 登录权限 

Vue自定义指令

全局: Vue.directive(指令名,配置对象)或 Vue.directive(指令名,回调函数)

局部:directives

配置对象中的3个回调函数:

  1. bind:指令与元素成功绑定时回调
  2. inserted:指令所在元素被插入页面是调用
  3. update:指令所在模板结构被重新解析时调用

使用directive

  1. 指令定义时不加v- 但使用时要加v-

  2. 指令名如果是多个单词 要使用‘-’链接的命名方式 不要用小驼峰命名

动态路由:

根据后端的数据展示不同的菜单

  1. 静态数据加载

  2. 公共数据复用

  3. 请求、响应拦截器

  4. 使用router、Routers动态添加路由

  5. vuex数据存缓

Vue生命周期:创建 挂载 更新 销毁

  1. 创建前:beforeCreate     获取不到数据 拿不到DOM元素

  2. 创建后: created             可以获取数据 但拿不到DOM元素

  3. 挂载前:beforeMount    可以拿到DOM元素 DOM元素没被解析

  4. 挂载后:mounted           可以拿到DOM元素  DOM元素被解析了

  5. 更新前:beforeUpdate   数据改变了 DOM没有发生变化

  6. 更新后:updated             数据改变了  DOM 也发生了改变

  7. 销毁前:beforeDestory   所有的事件监听和实例都可以用

  8. 销毁后:destoryed          所有的事件监听和实例都被销毁

v2和v3的区别:

理解响应式有助于理解代码逻辑

Vue3 基于proxy

Vue2 基于Object.defineProperty

v3比v2性能强

生命周期不同:

v3的setup代替了v2的创建前和创建后 其他的生命周期前面加个on

vue3支持碎片:就是可以有多个根节点

建立数据data:

  1. v2是把数据放入data中

  2. v3使用setup方法

父子传参不同:

  1. setup函数只能是同步 不能是异步
  2. setup内使用响应式数据时 需要通过value获取

3.vue2在data中声明变量,vue3在setup中用ref声明常量,reactive声明变量,return出来

vue框架的优点和缺点:

  1. vue优点:他属于轻量级框架 支持双向数据绑定、组件化、数据和结构的分离、虚拟dom、运行速度快

  2. vue缺点:实现多页应用时需要配置多入口 不够灵活 并且不支持IE8

js中slice,splice和split的区别:

  1. splice  可以做项目的添加 删除 修改 返回值是Array 

  2. slice  可以对数组进行部分截取 返回一个新的数组 

  3. split  可以把一个字符串分割成字符串的数组

如何终止forEeach循环:运用抛出异常:try catch

结束for循环: break 和 return

前端面试题之es6篇(附答案):www.jianshu.com/p/130daa314…

pinia和vuex:

  1. pinia是轻量级的 适合中小型应用  vuex是重量级的 对性能有影响

  2. pinia没有mutation 只有state getters action使用他来修改state的数据

  3. pinia默认存在内存中

  4. pinia语法上比vue更容易理解和使用

  5. pinia没有modules配置 每一个独立的仓库都是definStore生成出来的

key值的作用:他是一个标识符 给每一个唯一的id 

ref 和 reactive区别:

  1. reactive用于为对象添加响应式状态 获取数据不需要加.value 参数只能传入对象类型
  2. ref用于数据添加响应式状态 获取数据时需要加.value  参数可以传递任意数据类型

Vue 中强制更新视图:1.Vue.set  this.set  2. set   2. forceUpdate  (佛s)

js数组去重的方法:

  1. set()+Array.from()
  2. indexOf  建立一个空数组 然后循环遍历 判断数组是否已经含有当前元素 没有则存入
  3. includes 方法 判断是否包含元素
  4. 利用两层循环进行比较 使用splice删除 重复元素
  5. map  结构为键值对形式 将数组元素作map的值存入  然后结合has和set方法判断是否重复

vue Router实现原理:

vue-router实现单页面路由时 提供了两种方式hash和history

vue-router默认hash模式  他是模拟一个完整的url url改变时 页面不会重新加载  #是hash符号

Hash特点:

  1. url中带一个#号

  2. 可以改变url 但页面不会重新加载

  3. 只能修改#后面的部分 从#开始 后面的所有路径叫做路由的哈希值  哈希值不会发给服务器

  4. 通过window.onhashchange 监听hash的改变 实现无刷新跳转功能

  5. 每次改变一次hash 都会在浏览器的访问历史中增加一个记录

HIstory特点:

  1. 路径直接拼接在端口号后面 路径会发送给服务器 前端url要和发送请求后端url一致 否则会报404

  2. history APi缘故 低版本浏览器有兼容行问题

  3. history 利用了pushState和replaceState实现无刷新跳转的功能

  4. 通过参数stateObject可以添加任意类型的数据到记录中

Vue有什么设计模式: 单例模式 工厂模式 观察者模式 发布订阅模式

使用单例模式的场景:

  1. 有频繁实例化然后销毁的情况 

  2. 创建对象耗时过多或耗资源过多

  3. 频繁访问IO资源的对象 例如 数据库连接池或访问本地文件

原型和原型链:

    原型:每一个js对象创建的时候 就会与之关联另一个对象 这个对象就是我们所说的原型

    原型链: 当一个对象在查找一个属性时,自身没有就会根据__proto__属性向它的原型进行查找,如果还是没有,则向它的原型的原型继续查找,直至查到Object.prototype.__proto__也就是null,这样就形成了原型链

递归:就是在运行的过程中调用自己 

会在函数内部调用这个函数本身 要找出结束条件 不然就会一直调用

箭头函数和普通函数的区别:

  1. 外形不同

  2. 普通函数可以有匿名函数和具名函数  箭头函数都是匿名函数

  3. 普通函数可以构造函数 创建对象实例 箭头函数不可

  4. this指向 普通函数this指向调用他的对象 箭头函数指向window

从URL输入到页面展现到底发生什么?输入了一个域名 域名要通过DNS解析找到这个域名对应的服务器地址 通过TCP请求链接服务 通过WEB服务器返回数据浏览器根据返回的数据构建DOM树 再把css形成一个样式表 结合形成render树 页面通过重绘和回流的过程 渲染页面

TCP三次握手: 为了防止已失效的连接请求 突然又传送到了服务端,而产生错误

第一次由浏览器发起 告诉服务器要发送请求 第二次由服务器 告诉浏览器我准备接收了 第三次浏览器 我马上发了 准备接受吧

什么是重绘和回流:1. 重绘: 只影响元素的外观 风格 不会影响布局2. 回流: 布局 隐藏等改变而需要重建区别:回流必将引起重绘 而重绘不一定引起回流

单项数据流:

组件间传递数据是单向的 数据总是由父组件传递给子组件 子组件在其内部维护自己的数据 它无权修改父组件传递给他的数据如果要改变的话 vue会报错 这样做是为了组件间更好维护在开发中可能有多个子组件依赖于父组件的某个数据 如果子组件能改变父组件数据的话 一个子组件会引发依赖于这个父组件所有子组件的变化 

组件中data为什么是一个函数:

为了防止多个组件实例对象之间共用一个data 产生数据污染 而采用函数的形式 initData时会将其作为工厂函数返回全新的data对象

==和===的区别:

==:两个等号判断值是否相同

===:三个等号既要判断类型也要判断值是否相等

如何判断js的数据类型:

typeof:可以区分除了null类型意外的其他基本数据类型 返回值有:number、string、boolean、undefined、symbolinstanceof:一般用来判断引用类型 但不能正确判断基本数据类型 根据原型链中查找判断当前数据的原型对象 是否存在返回布尔类型

如何判断两个对象是否相等:

object.is(obj1,obj2)判断两个对象都引用地址是否一直 true则一致 false不一致