前端面试题初级、中级基础问题总结_中级前端 场景题

223 阅读13分钟

类似于我们ajax中get传参,在浏览器地址栏中显示参数
params则类似于post,在浏览器地址栏中不显示参数
三、router-link 【实现跳转最简单的方法】<router-link to='需要跳转到的页面的路径>

keep-alive是vue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件,我们能够知道,一般情况下,组件进行切换的时候,默认会进行销毁,如果有需求,某个组件切换后不进行销毁,而是保存之前的状态,那么就可以利用keep-alive来实现

路由导航守卫
1、全局前置守卫 beforeEach
2、全局解析守卫 beforeResolve ——⑥
3、全局后置钩子 afterEach ——⑦
路由独享守卫:beforeEnter ——④
组件内守卫:
1、beforeRouteEnter ——⑤
2、beforeRouteUpdate ——③
3、beforeRouteLeave ——①
每个守卫方法接收两个参数:
to: 即将要进入的目标 用一种标准化的方式
from: 当前导航正要离开的路由 用一种标准化的方式
可选的第三个参数 next

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

  1. 普通function的声明在变量提升中是最高的,箭头函数没有函数提升
  2. 箭头函数没有this,函数体内部的this对象就是定义的时候所在的对象,而不是调
    用时所在的对象
  3. 箭头函数没有arguments对象,该对象在函数体内不存在,若要用可使用rest参数
  4. 箭头函数不能为构造函数,不能被new,没有property
  5. call和apply方法只有参数,没有作用域
  6. 不可以使用yield命令,因此箭头函数不能做Generator函数

get和post的区别
1.在携带参数的时候,GET的参数是放在url中,以 " ? "分割url和传输数据,多个参数用 "&"连接。POST的参数是放在http请求体body中。
2.GET:浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);POST:浏览器先发送 header,服务器响应 100ms,浏览器再发送 data,服务器响应 200。
3.get用来获取数据,post用来提交数据
4.get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制,最长2048字节),而post无限制。

new做了什么
1 创建一个新对象;
2 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
3 执行构造函数中的代码(为这个新对象添加属性) ;
4 返回新对象

如何减少回流

  1. 给某个父元素增加子元素。如果要加多个子元素,最好使用documentfragment(不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染)
    2.改变元素宽高、border、字体大小。若改变多个属性,将这些属性定义在一个class中,直接修改class名,这样只用引起一次回流。
    3.修改一个元素的左右margin,padding。使用定位脱离文档流后改变位置
    4.获取元素的偏移量属性,浏览器为保证值的正确会回流取最新值。如scrollTop、scrollLeft、scrollWidth、offsetTop、offsetLeft、offsetWidth、offsetHeight等属性,做缓存,不频繁取
    5.不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
    什么是回流
    引起DOM树结构变化,页面布局变化的行为叫回流,且回流一定伴随重绘。

只是样式的变化,不会引起DOM树变化,页面布局变化的行为叫重绘,且重绘不一定会便随回流。

从输入url到页面加载都发生了什么
1.DNS解析URL得到IP
2.发起TCP连接(三次握手)
3.发送HTTP请求
4.浏览器响应请求(服务器处理请求并返回HTTP报文)
5.浏览器解析渲染页面
6.TCP连接关闭(四次挥手)

浏览器解析渲染页面过程
1.解析HTML文件生成Dom树
2.解析css,生成CSSOM规则树
3.合并Dom树和CSSOM树,生成渲染树
4.浏览器开始渲染页面,根据DOM树开始布局,渲染树也根据设置的样式对应渲染这些节点。(回流重绘发生在这个阶段)

问题1 vue
1.八个生命周期
beforeCreate(创建前)
created(创建后)
beforeMount(载入前)
mounted(载入后)
beforeUpdate(更新前)
updated(更新后)
beforeDestroy(销毁前)
destroyed(销毁后)

简单解说 created和mouted

  • created: 包括双向绑定相关内容(基本vue的初始化完成了)还未开始挂载 模板还未渲染成html 获取不到id 会报错 用于一般初始化数据列表
  • mouted页面已经渲染完毕 ,Dom操作一般是在mounted钩子函数中进行的,一般接收传值等
    2. v-if和v-show区别
  • v-if是控制dom节点的存在与否
  • v-show是控制元素的显示或隐藏

3. 父子组件之间的传值

  • 父传子
    子通过props接收
  • 子传父
    子通过 $ emit传递
  • 建立公共组件eventBus
    - eventbus怎么用
    可以在任何两个组件中进行传值,不局限于父子、祖孙或是兄弟组件,也可以说他是一种发布——订阅的设计模式。

    EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

vuex理解
vuex的状态存储是响应式的,当 vue组件中store中读取状态时候,若store中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变store中的状态的唯一途径就是显示 commit(提交)mutation,这样使得我们可以方便地跟踪每一个状态的变化。
主要有以下几个模块:

State: 定义了应用状态的数据结构,可以在这里设置默认的初始状态 基本数据
Getter: 允许组件从Stroe中获取数据, mapGetters辅助函数仅仅是将store中的 getter映射到计算属性。 从基础数据派生的数据
Mutation: 唯一更改store中状态的方法,且必须是同步函数。 同步 提交更改数据的方法
Action: 用于提交muatation, 而不是直接变更状态,可以包含任意异步操作。 异步 然后到mutations
Module: 允许将单一的store拆分为多个 sotre且同时保存在单一的状态树中 模块化vuex
vuex是基于vue框架的一个状态管理库。可以管理复杂应用的数据状态,比如兄弟组件的通信、多层嵌套的组件的传值等等。
问:除了vuex
有人讲用bus或者用vuex的,这当然行,但是vue提供了另外一种针对于爷孙或者其他的直系传值的方法,就是provide和inject。

注意,必须是直系的嵌套关系才能够使用

问题2 vue中data为什么是一个函数:
关键词:作用域
函数构成作用域 当data是一个函数时 每个组件实例都有自己的作用域 相互独立 互不影响

问题3vue中key的作用:
更高效的渲染更新dom 假如不加key的话 每改变一个参数 数据就请求一次 影响性能,通过key可以精准判断两个节点是否是同一个,另外,若不设置key还可能在列表更新时引发一些隐藏的bug
key值不能用index来设定 要给一个唯一的值
key值有个diff算法 渲染时如果有相同的key则不渲染dom节点不更新

问题4 vue双向绑定是怎么实现的
Vue 的双向绑定是一个语法糖
v-model原理:我们在vue项目中主要使用v-model指令在表单 input、textarea、select、等 表单元素上创建双向数据绑定, v-model本质上就是vue的语法糖,v-model在内部 为不同的输入元素使用不同的属性并抛出不同的事件:

text和 textarea元素使用value属性和input事件
checkbox和 radio使用checked属性和change事件
slect字段将 value作为prop并将change作用事件

<input v-model="something">
本质上相当于这样
<input v-bind:value="something" v-on:input="something = $event.target.value">
// 其实就是通过绑定一个something属性,通过监听input事件,当用户改变输入框数据的时候,
// 通过事件传递过来的事件对象中的target找到事件源,value属性表示事件源的值,从而实现双向数据绑定的效果

modal层通过defineProperty来劫持每个属性,一旦监听到变化通过相关的页面元素更新。另一方面通过编译模板文件,为控件的v-model绑定input事件,从而页面输入能实时更新相关data属性值。

问题5 怎么定义 vue-router 的动态路由?
在index.js文件里的path属性加上:/id

问题6 ​route和 router区别:
route路由信息 包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等
router是实例方法

问题7 NextTick
nextTick可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM

问题8 解决vuex页面刷新数据丢失问题

  1. 将vuex的数据直接缓存 不安全,不适用大数据量的存储
  2. 在页面刷新时 再次请求远程数据 动态更新vuex
  3. 请求远程数据 在页面刷新之前 缓存 在App.vue中

问题9 路由导航守卫
1.前置路由守卫beforeEach
to 即将要进入的路由对象
from 当前导航正在离开的路由
next 调用方法后 才能进入下一个钩子函数
判断用户是否登录
2.后置钩子aferEach
没有next

问题10. MVVM的理解
视图更新 数据更新 数据更新 视图更新
是采用数据劫持结合,发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者。

问题11 vue解决用户不同角色不同权限问题
vue-element-admin

问题12 vue-router两个页面之间怎么传值
this.router.push传递this. router.push传递 this.route.parmas.id接收

问题12 小程序生命周期
1.onLauch 页面加载时触发
2.onshow 发送数据请求
3.onHide页面隐藏/切入后台时触发, 如底部 tab 切换到其他页面或小程序切入后台等
4.onReady: 页面初次渲染完成
5.onUnload() 页面卸载时触发,如redirectTo或navigateBack到其他页面时上拉加载 下拉刷新
下拉刷新用view代替scroll-view,设置onPullDownRefresh函数实现
上拉加载 onReachBottom

问题13 小程序的双向绑定和vue哪里不一样
必须通过this.setData取值

问题14 bindtap和catchtap的区别:
bindtap不会阻止事件绑定向上冒泡
catchtap可以阻止事件绑定向上冒泡

问题15.computed与watch分别用在什么场景,有什么区别
1.从缓存角度
computed支持缓存
watch不支持缓存
2.从异步
computed不支持异步
watch支持异步
3.总结
computed一个数据需要进行复杂计算
watch一个数据需要被监听并且做一些操作
4.实例
computed 购物车或者地址
watch搜索
场景的话 computed 一般就用来数据合成
watch的话 用来监听路由变化 或者数据变化 来执行相应的动作

Watch会监听data中的变量 被监听者参数改变后会触发回调 频繁改变的话会连续触发非常消耗性能
只要被监听的数据发生改变,就会触发对应的逻辑代码
如果被监听的数据是个对象(或数组),对象(或数组)中的属性发生改变时,监听是不会触发上的
但是开启深度监听:只要obj中的任何一个属性发生改变,都会触发相应的代码,数组也是同样如此
computed.定义一个数据,进行一次复杂计算,该方法不会频繁触发 非常节省性能

问题16 call apply bind
a.相同点
都可以改变this指向
b.不同点
1.从是否立即执行
bind不立即执行
call和apply立即执行
c.从接收参数的方式
1.call 和appply第一个参数相同都是上下文的对象
2.call和apply第二个参数 call是列表 apply是数组
d.从浏览器兼容
1.bind这个方法在IE6~8下不兼容

问题17 一个页面从输入url到页面加载完成究竟经历了些什么
1.输入地址
2.查看缓存
3.寻找IP
4.三次挥手
5.浏览器向服务器发送http请求 请求数据包
6.服务器处理请求 将数据返回到浏览器
7.浏览器收到http响应
8.浏览器渲染 解析html源码
9.css js
10.客户端与服务器交互
11.ajax查询

问题18 http与https
a.从安全角度
1.https在HTTP的基础上加入了SSL/TLS协议 安全性好
2.http以明文发送 数据传输不加密
b.从握手协议时间
1.https时间长
2.http时间短
c.概念
1.http超文本传输协议
2.https安全套接字层超文本传输协议

问题19 hash模式和history模式的区别
1.hash模式url 尾巴后的 # 号以及后面的字符
2.兼容方面
hash 能兼容到IE8
history 只能兼容到 IE10

问题20 var let const区别
a.块级作用域角度
1.var没有块级作用域
2.let const有块级作用域
b. 变量提升角度
1.var 可以变量提升
2.let const 不存在变量提升
c.不可重复声明角度
1.var 可以重复声明
2.let const不能重复声明
d.const和let区别
对于const来说,只声明不赋值,就会报错
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动

问题21 JS事件循环机制(event loop)之宏任务、微任务
JavaScript是单线程的语言在这里插入图片描述

	Event Loop是javascript的执行机制
		宏任务一般是:包括整体代码script,setTimeoutsetInterval、setImmediate
		微任务:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTickMutationObserver 记住就行了
		同步代码:console.log/settimeout/new promise()等

事件分类
宏任务:setTimeout/setInterval/ requestAnimationFrame的回调函数

微任务:promise.then()/process.nexttick中的回调函数

同步代码:console.log/settimeout/new promise()等

执行顺序
执行顺序,先宏任务再微任务,主线程上执行的同步代码也算是一个宏任务。

无await: 同步代码(主线程同步代码也是一个宏任务) ——》遇见宏任务将其加入宏任务队列,遇见微任务将加入微任务队列——》微任务队列所有任务——》(先进先出顺序)宏任务队列的某个任务() ——》遇见宏任务将其加入宏任务队列,遇见微任务将加入微任务队列 循环

有await: promise中执行resolve才会添加then()到微任务,否则不会,添加到微任务,并且await语句后的语句不会执行

同步代码(主线程同步代码也是一个宏任务)—》遇见宏任务将其加入宏任务队列,遇见微任务将加入微任务队列 ——》遇见调用async方法,执行async方法——》async方法中遇见await语句,执行await语句后的方法——》await后方法有promise.then()将其加入微任务队列——》跳出此时async方法——》执行外部同步代码(遇见宏任务将其加入宏任务队列,遇见微任务将加入微任务队列)——》同步代码执行完毕——》返回当时async方法,执行后续代码语句——》后续同步代码执行完毕——》z执行微任务队列所有任务——》执行宏任务队列某个任务循环
问题22 ES6
新添加了声明变量 let const import class类
1.let const
2.解构赋值
3.模板字符串
4.箭头函数
5.set()
6.map()
7.class类
8.async await
9.promise
10.for … of遍历获取的是对象的键值只遍历当前对象不会遍历原型链,for … in 获取的是对象的键名,会遍历对象的整个原型链,性能非常差

	扩展对象:
	1.使用JQuery的extend方法o3 = $.extend(o1, o2)  // 合并 o1 和 o2, 将结果返回给 o3
	2.var obj = Object.assign(o1, o2, o3)
	3.遍历赋值法 
	合并数组:
	1.concat()方法     2.  for循环    3.  apply

问题23 跨域
vue项目中vue.config.js配置proxy
vue项目中修改谷歌浏览器属性-快捷方式-目标- --args --disable-web-security --user-data-dir=D:\temp
Nginx代理——生产环境 修改nginx.conf文件下的serve下配置

问题24 为什么会出现跨域
浏览器的同源策略导致了跨域, 浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域 就是浏览器在搞事情

在vue里面使用http代理,在vue项目里根目录下找到 vue.config.js文件,在 proxy中设置跨域
nginx实现跨域的原理,把web项目和后端接口项目放到一个域中,这样就不存在跨域问题,然后根据请求地址去请求不同服务器

问题25 前端性能优化
vue项目优化

		(1)代码层面的优化
			v-if 和 v-show 区分使用场景
			computed 和 watch 区分使用场景
			v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
			长列表性能优化
			事件的销毁
			图片资源懒加载
			路由懒加载
			第三方插件的按需引入
			优化无限列表性能
			服务端渲染 SSR or 预渲染
			
		(2)Webpack 层面的优化
			Webpack 对图片进行压缩
			减少 ES6 转为 ES5 的冗余代码
			提取公共代码
			模板预编译
			提取组件的 CSS
			优化 SourceMap
			构建结果输出分析
			Vue 项目的编译优化
			
		(3)基础的 Web 技术的优化
			开启 gzip 压缩
			浏览器缓存
			CDN 的使用
			使用 Chrome Performance 查找性能瓶颈

首屏优化

静态文件缓存方案
前端的资源动态加载
a. 路由动态加载,最常用的做法,以页面为单位,进行动态加载。
b. 组件动态加载(offScreen Component),对于不在当前视窗的组件,先不加载。
c. 图片懒加载(offScreen Image),同上。值得庆幸的是,越来越多的浏览器支持原生的懒加载,通过给img标签加上loading="lazy来开启懒加载模式。
减少请求的数量
页面使用骨架屏
使用ssr渲染
前端做一些接口缓存

问题26 H5
em rem px vw vh rpx 单位的区别
1.默认情况下像素px是相对于屏幕分辨率而言
2.em 是相对长度单位。相对于当前元素的font-size em的大小取决于父级的字体大小尺寸 当父级的字体大小为20px,子级的1em就是20px
3.rem相对的只是HTML根元素 跟整个body的font-size有关系 只要html的font-size大小不变,1rem所代表的font-size大小就不会变,rem只取决于html的font-size
4.rpx小程序 多少px就是多少rpx
5.vw:1vw等于视口宽度的1%
6.vh:1vh等于视口高度的1%

问题27 css3动画、H5新特性

问题28 HTML&CSS: 浏览器内核、flex布局、两/三栏布局; BFC、清除浮动。

盒模型
content-box
盒模型的宽度为width的宽度
公式为: width = 内容宽度

border-box
边框模型的宽度为内容的宽度,加上内边距的宽度,再加上边框的宽度
公式为: width = 内容的宽度 + padding + border

水平垂直居中
定位和需要定位的元素的margin减去宽高的一半
定位和margin:auto
绝对定位和transform: translate(-50%,-50%)
display: flex;
justify-content: center;
align-items:center;

问题29
函数节流: 指定时间间隔内只会执行一次任务;

函数防抖: 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行

问题30 内存中的堆和栈
栈:先进后出,自动分配释放使用完,自动销毁
堆:先进先出,手动释放,容易内存泄漏 由程序员手动分配内存
问题31 rem实现
核心思想:百分比布局可实现响应式布局,而rem相当于百分比布局。

实现手段:动态获取当前视口宽度width,除以一个固定的数n,得到rem的值。表达式为rem = width / n。
通过此方法,rem大小始终为width的n等分。

核心代码块:

        // 动态为根元素设置字体大小
        function init () {
      // 获取屏幕宽度
          var width = document.documentElement.clientWidth
      // 设置根元素字体大小。此时为宽的10等分
          document.documentElement.style.fontSize = width / 10 + 'px'
        }

     //
     首次加载应用,设置一次
        init()
        // 监听手机旋转的事件的时机,重新设置
        window.addEventListener('orientationchange', init)
        // 监听手机窗口变化,重新设置
        window.addEventListener('resize', init)

项目中如何rem适配

  1. 需要把px 转化成rem 引入postcss-pxtorem用于将单位转化为 rem
  2. 在项目分根目录下配置postcss.config.js里的rootValue 设置基准值为37.5 (一般以iphone6的屏幕宽度的十分之一 作为基准值 37.5) lib-flexible用于动态设置 rem 基准值

需要根据当前的屏幕的变化调整当前font-size的大小

理解:上面代码实现了,无论设备可视窗口如何变化,始终设置rem为width的1/10.即实现了百分比布局

问题32 sass优势
@import规则,但不同的是,sass的@import规则在生成css文件时就把相关文件导入进来。这意味着所有相关的样式被归纳到了同一个css文件中,而无需发起额外的下载请求。

混合器(其实就是属性代码块,相当于implements)
@mixin 和 @include

如果你的整个网站中有几处小小的样式类似(例如一致的颜色和字体),那么使用变量来统一处理这种情况是非常不错的选择。但是当你的样式变得越来越复杂,你需要大段大段的重用样式的代码,独立的变量就没办法应付这种情况了。你可以通过sass的混合器实现大段样式的重用。

混合器使用@mixin标识符定义。看上去很像其他的CSS @标识符,比如说@media或者@font-face。这个标识符给一大段样式赋予一个名字,这样你就可以轻易地通过引用这个名字重用这段样式。下边的这段sass代码,定义了一个非常简单的混合器,目的是添加跨浏览器的圆角边框。


@mixin rounded-corners {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

然后就可以在你的样式表中通过@include来使用这个混合器,放在你希望的任何地方。@include调用会把混合器中的所有样式提取出来放在@include被调用的地方。如果像下边这样写:


notice {
  background-color: green;
  border: 2px solid #00aa00;
  @include rounded-corners;
}

问题33 less
1.css预处理器
2.支持变量
3.支持函数
4.支持混用
5.支持简单计算
6.易维护

问题34 typeof其实就是判断参数是什么类型的实例,就一个参数
它返回值是一个字符串,该字符串说明运算数的类型。(typeof 运算符返回一个用来表示表达式的数据类型的字符串。 )
typeof 一般只能返回如下几个结果:“number”、“string”、“boolean”、“object”、“function” 和 “undefined”

console.log(typeof a);    //'undefined'

    console.log(typeof(true));  //'boolean'

    console.log(typeof '123');  //'string'

    console.log(typeof 123);   //'number'

    console.log(typeof NaN);   //'number'

    console.log(typeof null);  //'object' 

    var obj = new String();

    console.log(typeof(obj));    //'object'

    var  fn = function(){};

    console.log(typeof(fn));  //'function'

    console.log(typeof(class c{}));  //'function'

总结: typeof运算符用于判断对象的类型,但是对于一些创建的对象,它们都会返回’object’,有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到 instanceof 运算符
push
1.this.$router.push()

描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。

2.this.$router.replace()

描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。

3.this.$router.go(n)

相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面

引用类型数据: 也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。

这里分享一份由字节前端面试官整理的「2021大厂前端面试手册」,内容囊括Html、CSS、Javascript、Vue、HTTP、浏览器面试题、数据结构与算法。全部整理在下方文档中,共计111道

HTML

  • HTML5有哪些新特性?

  • Doctype作⽤? 严格模式与混杂模式如何区分?它们有何意义?

  • 如何实现浏览器内多个标签页之间的通信?

  • ⾏内元素有哪些?块级元素有哪些? 空(void)元素有那些?⾏内元 素和块级元素有什么区别?

  • 简述⼀下src与href的区别?

  • cookies,sessionStorage,localStorage 的区别?

  • HTML5 的离线储存的使用和原理?

  • 怎样处理 移动端 1px 被 渲染成 2px 问题?

  • iframe 的优缺点?

  • Canvas 和 SVG 图形的区别是什么?

JavaScript

  • 问:0.1 + 0.2 === 0.3 嘛?为什么?

  • JS 数据类型

  • 写代码:实现函数能够深度克隆基本类型

  • 事件流

  • 事件是如何实现的?

  • new 一个函数发生了什么

  • 什么是作用域?

  • JS 隐式转换,显示转换

  • 了解 this 嘛,bind,call,apply 具体指什么

  • 手写 bind、apply、call

  • setTimeout(fn, 0)多久才执行,Event Loop

  • 手写题:Promise 原理

  • 说一下原型链和原型链的继承吧

  • 数组能够调用的函数有那些?

  • PWA使用过吗?serviceWorker的使用原理是啥?

  • ES6 之前使用 prototype 实现继承

  • 箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?

  • 事件循环机制 (Event Loop)

开源分享:docs.qq.com/doc/DSmRnRG…