[前端高频面试] 2023年初级、中级面试题解

单纯为了自己面试方便,整理一些高频面试题,2023希望每个前端小伙伴找到心仪的工作!!

目录

「自我介绍(仅供参考)」

「HTML、CSS相关」

 » H5有哪些新特性?

 » 浏览器渲染机制、重排、重绘

» 简述CSS盒模型

» 如何让盒子水平垂直居中

» 如何实现一个三角形?

» CSS样式优先级

» display:none 和 visibility: hidden 的区别?

» 去除浮动的几种方式?(问可顺带答出BFC)

» 什么是BFC?BFC布局规则是什么?如何创建BFC?

» cookies、localStorage、sessionStorage的区别?

「JS」

» 什么是闭包?

» 作用域、作用域链、变量提升、函数提升分别是什么?

» JS有哪些数据类型?typeof、instanceof、类型转换

» 原型和原型链

» 继承(含ES6)、多种继承方式

» this指向、new关键字

» bind、call、apply的区别?

» JS 的设计模式?

» 深拷贝和浅拷贝

» TS 和 JS 有什么区别,优点和缺点

» 什么是事件冒泡、事件捕获、事件委托机制?

» 普通事件和事件绑定有什么区别?

» EventLoop(线程机制)

» 防抖和节流

» 函数柯里化

「ES6」

» var 、 const、 let 的区别?

» Promise的理解

» Promise.all 和 Promise.race

» 箭头函数和普通函数的区别?

» 什么时候不能使用箭头函数?

» Set 和 Map 的区别?

» map 和 forEach 的区别?

» for...in 和 for...of 的区别?

「Ajax API模块」

» ajax同源策略的理解,如何解决跨域?

» HTTP状态码有哪些?

» get 和 post 的区别?

» HTTP 和 HTTPS 的区别?

» 浏览器从输入url到渲染页面,发生了什么?

» 输入url 后 http请求的完整过程是什么?

» 浏览器缓存原理?(网站怎么优化)

「Vue2和Vue3」

» vue2 和 vue3的区别?

» vue2相比vue3有什么缺点?

» vue3有哪些新特性吗?它们带来什么影响

» vue2 数据双向绑定原理

» v-model的实现以及实现原理?

» MVVM开发模式的理解?

» vue组件通信有哪几种方式?

» 的作用是什么?或者vue切换页面如何保存状态?

» vuex有哪几种属性?

» vuex和pinia的区别,优缺点?

» vue-router路由实现原理是什么?有什么不同

» $route 和 $router的区别?

» vue中key 的作用是什么?

» 虚拟DOM和真实DOM的区别?

» computed 、watch 、methods的区别?

» 组件中的data为什么是一个函数?

» v-if 和 v-show的区别?

» vue数据变化视图不更新如何解决?

» 父子组件生命周期渲染顺序?

「前端性能优化」

» 前端性能优化的几种方式

» Vue首屏渲染优化有哪些?

» Vue项目做了哪些优化?

» CDN加速静态资源是什么?

「前端工程化」

» express 和 koa 有什么区别?

» 谈谈你对webpack的看法

» 前端为什么要进行打包和构建?

» webpack的基本功能有哪些?

» 常见的Webpack Loader?解决什么问题

» Loader 和 Plugin 的不同?

» 有哪些常见的 Plugin插件?解决什么问题的?

» Vite 和 Webpack区别?

» 为什么Vite 比 webpack速度快?

「职业技能规划、人事面试」

» 你的职业规划是什么?

» 为什么从上一家公司离职?

» 前端是如何学习的?

» 项目中有遇到什么难题?

» 还有什么想问的

「自我介绍(仅供参考)」

注意: 别紧张,目光注视面试官,不要有小动作,自信!!自信!!自信!!

面试官您好,我叫XXX,目前从事前端开发工作已经有X年,我上家公司是一个外包公司做别人的项目的,主要从事H5页面,后台管理系统和小程序等项目开发,其中H5和PC端是一套做保险相关业务的,在做H5的时候遇到过一个bug就是做微信SKD分享签名无效,请求的后台数据也返回了,后端就反映不是自己的问题,但反复排查发现是后端返回的签名和公众号配置的签名不一致,导致签名无效,分享失败...我呢平常喜欢逛一些技术社区丰富自己的技术,像知乎,掘金之类,并且自己也独立开发了个人博客网站,记录自己的工作总结和学习心得。 我的性格比较温和,跟同事朋友相处时比较外向,在工作中代码开发时我喜欢全心全意的投入,对于工作我也抱着认真负责的态度。面试官,以上是我的介绍,谢谢。

「HTML、CSS相关」

 » H5有哪些新特性?

  • 语义化标签: main、header、nav、article、section、aside、footer 
语义化指的就是合理正确的使用语义化标签来创建页面结构,如: header、nav、footer,从标签上就能看出这个标签的作用,而不是滥用div 语义化的优点: 代码结构清晰,易于阅读、利于开发和维护 方便其他设备解析(如屏幕阅读器)根据语义渲染网页 有利于搜索引擎优化(SEO),搜索引擎爬虫会根据不同的标签来赋予不同的权重

» CSS3有哪些新特性?

其实并不存在真正意义上的CSS3,因为我有阅读W3C文档

  • css3并不是一个单一的规范,而是一系列独立模块的集合,这些模块扩展了css的功能

  • 这种模块化的方法允许不同的特性以不同的速度发展,可以更快的标准化一些特性,不必等待整个规范的完成

选择器 新的属性选择器, 如: [attr^=value] 属性值以特定字符串开头 结构性伪类: nth-child nth-last-child first-child 背景和边框 边框图片:border-image, 允许使用图片来创建边框 多重背景,支持在单个元素上使用多个背景图片 文本效果 文本阴影: text-shadow 文本溢出: taxt-overflow 转换和动画 2D 和 3D 转换( transform ),包括旋转( rotate )、缩放( scale )、倾斜( skew )和平移 ( translate )。 CSS 动画( animation ),允许定义关键帧动画,控制动画序列

» 浏览器渲染机制、重排、重绘

网页生成过程:

  • HTMl被HTML解析器解析成DOM树
  • css被css解析器解析成CSSOM树
  • 结合DOM树和CSSOM树,生成一颗渲染树(Render Tree)
  • 生成布局(flow),将所有渲染树的所有节点进行平面合成
  • 将布局绘制(paint)在屏幕上

重排(也叫回流):当改变DOM元素位置和大小时,浏览器需要重新计算元素的几何属性,将其安放在界面的正确位置,这个过程叫做重排

触发:

  1. 添加或者删除DOM元素
  2. 元素位置改变、元素尺寸改变、内容改变
  3. 浏览器窗口尺寸改变

重绘:  第一次渲染内容称为绘制,之后重新渲染叫重绘;一个元素的外观发生改变,但布局没有发生变化,重新绘制外观的过程

触发: 改变元素的颜色、文字颜色、背景色、边框颜色,样式等属性

总结:重排一定会引起重绘,重绘不一定会引起重排,重排的性能消耗比重绘大

尽量减少或者避免回流的发生,这个过程是非常消耗性能的

如何避免性能影响?

  1. css避免使用table布局,避免设置多层内联样式
  2. 避免频繁操作DOM,对于大量插入DOM操作,建议使用文档片段;用js修改样式,最好不要直接写样式,而是通过class来修改样式

» 分析将JS文件放在HTML文档的不同位置对加载和执行的影响

通常在开发中,JavaScript元素的编写位置我们会放在头部或者尾部,它们是会有区别的。 情况一:普通JavaScript放在头部 1. 当JavaScript文件放置在文档的头部时,浏览器在解析HTML到达<script>标签时会暂停,进行脚本的下载和执行。 2. 这意味着,直到JavaScript执行完成,页面的其余部分(如HTML和CSS)才会继续加载。 3. 这种做法通常会导致可见的延迟,尤其是当脚本文件较大或网络条件较差时。 4. 另外如果涉及到DOM元素操作,因为DOM还没有构建完成,所以操作DOM可能会失败,也需要慎重操作。 情况二:普通JavaScript放到尾部 1. 将JavaScript放在页面底部是一种常见的做法,以提高页面的加载速度。 2. 这样,浏览器可以先加载页面的所有HTML和CSS内容,使用户尽快看到页面的结构和样式,而脚本将在页面的内容完全加载之后才开始下载和执行。 3. 这种方法通常可以提高首次渲染时间和用户感知的加载速度。 4. 当JavaScript放置在页面的底部时,它将在大部分或全部DOM元素已经加载后执行,从而减少了因DOM元素尚未加载而导致的错误。 我们可以结合前面学习defer和async来回答: 1. 为了进一步提升性能,现代的开发实践中常常利用async和defer属性。 2. defer属性让脚本的下载与DOM解析同步进行,但延迟到整个页面解析完成后再执行。 3. async属性允许浏览器异步下载脚本,而不阻塞DOM的解析,脚本会在下载完后立即执行。 4. 这两种属性都有助于优化加载时间和用户体验,选择使用哪一种取决于脚本的具体作用和需求

» 简述CSS盒模型

  • 标准盒子(内容盒子): 给盒子设置box-sizing:content-box  , 宽度 = 内容的宽度,如果后期添加了 padding 或border就会使盒子向外扩张
  • IE盒模型(边框盒子): box-sizing:border-box, 设置的宽度 = 内容宽度 + padding + border; 添加的padding和border就在原先设置的width里,padding和border越大就会向内部content扩张,导致content变小

» 如何让盒子水平垂直居中

  1. 绝对定位方法: top、bottom、left、right设置为0, margin:auto
  2. 绝对定位方法:top:50%;left:50%; margin-left: 宽度的一半; margin-top:高度的一半
  3. 绝对定位方法:不确定div的宽度和高度,利用transform: translate(-50%,-50%)
  4. flex弹性盒布局:父:display:flex; 垂直居中-align-items:center; 水平居中-justify-content:center

» 如何实现一个三角形?

.box { width: 0; height: 0; line-height: 0; font-size: 0; border: 50px solid transparent; border-left-color: pink; } 想要哪个方向的三角设置哪个方向的边框颜色

» CSS样式优先级

!important(无穷大)  > 行内样式(1000) > id选择器(100) > 类选择器(10)、属性选择器、伪类选择器  > 标签选择器、元素选择器(1) > 继承或 *通配符选择器(0)

  1. id选择器 ( # myid)
  2. 类选择器( .box )    属性选择器 (a[resl = 'external'])  伪类选择器 (a:hover, li:nth-child())
  3. 标签选择器 (p,div,h1-h6)       伪元素选择器 (p::after    p::before)

» display:none 和 visibility: hidden 的区别?

共同点: 都用来隐藏元素

不同点:

  • display:none; 隐藏元素不占据任何空间,会导致重排和重绘
  • visibility:hidden; 隐藏元素的时候还会占据空间,只是内容不可见,只会导致重绘
  • display:none; 非继承属性,子孙节点的消失是因为渲染树消失造成的,通过修改子孙节点属性无法显示
  • visibility:hidden; 继承属性,子孙节点的消失是由于继承了hidden,通过设置visibility:visible;可以让子孙节点显示

» 去除浮动的几种方式?(问可顺带答出BFC)

浮动的元素会脱离文档流,什么叫脱离文档流,举个栗子: 有一天你和你老板说:世界那么大,你想去看看,那之后你老板就管不了你了。脱离文档流也同理,一个元素一旦浮动,就会脱离文档流,那父元素也就管不了他了,布局就会往前推进, 父元素就会出现高度塌陷的问题。

  1. 将父级设置成浮动,float:left 缺点:父级设置浮动了,那爷爷不也受影响了,又得解决爷爷的高度塌陷问题,无限套娃🪆
  2. 给父级设置定位absolute, 缺点:也会脱离文档流,影响布局
  3. 给父级设置overflow:hidden,缺点:文本过长,且包含英文时,会出现英文文本被隐藏
  4. 给父级设置对应的高度,缺点:浮动元素定高还好,如果不定高的情况就不灵活了
  5. 末尾增加空的div,设置clear:both,缺点:增加了一个div标签
  6. 给父级添加伪元素进行clear, ::after,伪元素不会被当作dom标签渲染出来(目前最优解)

» 什么是BFC?BFC布局规则是什么?如何创建BFC?

针对BFC网上也是有特别多的说法,我也看过很多视频和文章讲解,后来我查W3C文档是这么说的

在标准流中,我们所有的盒子,不管是行内盒子还是块级盒子,都属于一个FC(格式化上下文),块级盒子属于BFC(块级格式化上下文),行内盒子属于IFC(行内格式化上下文);  BFC就是决定盒子是如何排布的,在BFC中,box盒子会在垂直方向一个挨着一个排布,垂直方向的间距是由margin来决定的,并在同一个BFC中,两个相邻的box之间的margin会重叠; 这个就是BFC官方解释!!

哪些元素会生成BFC?

创建BFC的方式有很多,要根据不同的场景去使用不同的方式;

  • 比如HTML根元素本身就创建一个BFC

  •  浮动元素: float
  • 绝对定位元素absolute和固定定位元素fixed
  • 在开发中我们想要在很多情况下不影响布局创建BFC,常用的就是将overflow设置为非visible,比如auto就可以创建BFC

​​​​​​​问: 如何解决BFC折叠问题?

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width= , initial-scale=1.0"> <title>Document</title> </head> <style> .box1 { height: 100px; background-color: red; margin-bottom: 100px; } .box2 { height: 100px; background-color: pink; margin-top:50px; } .container { overflow: auto; } </style> <body> <!-- 问题: html根元素本身就会创建一个BFC, box1和box2都在同一个BFC下面 同一个BFC中,相邻的两个盒子的margin会发生一个重叠,所以这两个盒子的margin还是100px --> <!-- 解决方法:给box1 创建一个新的BFC,创建一个container盒子进行包裹, 添加 overflow属性既不会影响布局,还能创建BFC--> <div> <div></div> </div> <div></div> </body> </html>

 » cookies、localStorage、sessionStorage的区别?

  • 数据生命周期: 
    • cookie:可以设置失效时间,默认浏览器关闭失效
    • local:本地持久化存储,除非手动删除否则永久保存
    • session:仅在当前页有效,浏览器关闭或者页面关闭就会被清除
  • 存放数据大小:
    • cookie:数据不能超过4k,主要用于保存登录信息,比如登录某个网站看到“记住密码”,通过往cookie存入一段辨识用户的数据来实现的
    • local、session:虽然也有存储大小限制,但比cookie大很多,一般在5M或更大
  • http请求
    • cookie每次请求都会携带http头中,如果使用cookie保存过多数据会带来性能问题;
    • local、session在浏览器中保存,不参与和服务器的通信
  • 作用域不同
    • sessionStorage:不在不同的浏览器窗口中共享,即使在同一个页面
    • localStorage和cookie:在所有同源窗口中都是共享的;只要浏览器不关闭,数据仍然在

  从安全性来说,因为每次http请求都会携带cookie,这样浪费了带宽,所以cookie尽可能少用,此外cookie需要指定作用域,不能跨域调用,限制很多;local和session可以用来在页面传递参数,session可以保存一些临时的数据,防止用户刷新页面丢失一些参数

「JS」

» 什么是闭包?

通俗一点就是打通了一条函数外部访问函数内部作用域的通道,正常情况下函数外部是访问不到函数内部作用域变量的

如何判断闭包:函数嵌套函数、内部函数被return、内部函数调用外层函数的局部变量

优点:隔离作用域,不造成全局污染

缺点:导致函数变量一直保留在内存中,过多的闭包会导致内存泄露(任何对象不需要它后仍然还在)

闭包的主要作用:延伸变量的作用范围

适用场景:封装组件、for循环和定时器结合、节流和防抖也会用到

vue中出现内存泄露的情况: 

  1. 全局变量引起的内存泄露
  2. 监听事件没有解绑,在页面销毁的时候,顺便解绑,释放内存,原则不用的东西及时归还
  3. echarts页面切换的时候,还保留在内存中,导致浏览器卡顿

 » 作用域、作用域链、变量提升、函数提升分别是什么?

作用域: js识别变量的范围,包括全局作用域(任何地方都可访问的变量)、局部作用域(只在函数内部定义的变量范围)、块级作用域(ES6用const、let定义的变量都认为是块级作用域中的变量)

作用域链: 从当前作用域开始一层一层向上寻找某一个变量,直到找到全局作用域还是没找到,就放弃!这查找的过程,就是作用域链

变量提升: 使用var关键字定义的变量,只提变量,不提赋值

函数提升: 使用function声明的函数,只提函数,不调用函数

» JS有哪些数据类型?typeof、instanceof、类型转换

js属于弱类型语言(支持隐式转换)

数据类型: String、Number、Boolean、Null、undefined、Object(function,array--堆内存)、symbol(ES10BigInt--栈内存)

typeof: 基本数据类型除了null返回Object,其他都返回对应的类型; 引用数据类型除了函数其他都返回Object

instanceof: 判断一个对象是否是另一个对象的实例,注意只能用来判断对象

null表示空对象,undefined表示已在作用域中声明但未赋值的变量

» 原型和原型链

原型:js中万物皆对象,每一个对象都有自己的属性,js中如何让多个对象共用一个或多个方法呢?原型的出现就是为了解决这个问题,每一个对象都有一个与他关联的原型对象,每次获取对象属性都是一次查找过程,在对象的自有属性中找不到就会去查找它的原型对象

原型链:原型连成一条链,当我们访问一个对象的属性时,如果这个对象内部没有这个属性,我们就会去它的原型对象中查找这个属性,这个原型对象又会有自己的原型,于是这样一直向上查找,直到找到Object为null的时候,这个查找的过程就是原型链

总结: 

  1. 原型存在的意义就是组成原型链
  2. 原型链存在的意义就是继承:访问对象属性时,在对象本身找不到,就会按原型链一层一层找,说白了就是一个对象可以访问其他对象的属性
  3. 继承存在的意义就是属性共享:好处:1.代码重用2.可扩展,不同对象可以继承相同的属性,也可以定义只属于自己的属性

» 继承(含ES6)、多种继承方式

  • 原型链继承 – 重写prototype
  • 构造函数继承 – Parent.call(this)
  • 组合继承 – 重写prototype + Parent.call(this)
  • 原型式继承 – Object.create(Parent),不添加额外的属性和方法
  • 寄生式继承 – Object.create(Parent),添加额外的属性和方法
  • 寄生组合式继承 – Object.create(Parent) + Parent.call(this)
  • ES6类的继承 – extends + super(props)
  • 原型链继承口述:写个父类、子类,子类的原型为父类的实例,子类.prototype = new 父类,修正子类原型为子类本身, 子类.prototype.constructor = 子类, new 子类即可调用父类方法,构造函数继承,写个父类、子类,在子类中父类.call(this)即可实现

» this指向、new关键字

  • 构造器函数调用:this指向new创建的新对象
  • 箭头函数不绑定this: 捕获在上下文的this,在哪里定义指向谁
  • 全局函数中,this指向的是window
  • 普通函数this,谁调用指向谁

     new操作符干了什么?

  1. 内存中创建一个新对象
  2. this指向这个新对象
  3. 执行构造函数里边代码添加属性
  4. 返回新对象(所以构造函数里不用return)

» bind、call、apply的区别?

  • 都可以改变函数内部this指向
  • call、apply可以调用函数,bind不会调用函数