【前端八股文·上】HTML+CSS+Vue 详细篇

文章目录


前言

快乐是什么?快乐就是…快乐就是当你…快乐就是当你想找一篇比较全的前端八股文的时候我恰好整理了
以下都是我在复盘的时候从各处搜罗来的干货,仅供学习


一、HTML

1. src和href的区别

都是用来加载外部资源的

区别srchref
用于指定外部资源(通常是脚本文件、图像文件、音频文件等)的 URL用于指定超链接的 URL,表示链接的目标资源。
主要用于指定要嵌入到页面中的外部资源,比如 <script>、<img>、<audio>、<video>、<iframe> 等标签。主要用于 <a>、<link>、<base> 标签等。
浏览器会根据 src 属性的值发送一个额外的 HTTP 请求来获取这个资源。href 属性指向的资源可以是当前文档中的锚点(#section)、外部 URL、邮件地址等。
对于一些标签(比如 <script>、<img>、<iframe>)来说,src 是必需的属性,缺少 src 可能会导致标签无法正常工作。点击带有 href 属性的链接会导航到指定的 URL,或者在 <link> 标签中加载外部样式表。
当浏览器解析到该元素时,会暂停其他资源的加载和处理,直到该资源加载完成。浏览器解识别到它指向的位置,将其下载的时候不会阻止其他资源的加载解析

## 2. HTML5新增特性 引入了许多新特性和改进,以下是其中一些主要的特性:

语义化标签: 引入了一系列新的语义化标签,如 <header>、<footer>、<nav>、<article>、<section> 等,使得页面结构更加清晰明了,有助于搜索引擎优化和开发者理解代码。

多媒体支持:提供了内置的多媒体支持,包括<video> 和 <audio>标签
Canvas绘图Canvas 元素允许开发者使用 JavaScript 绘制图形、动画和其他图像,而不需要使用基于插件的技术,如 Flash

SVG支持:支持矢量图形(SVG),使得在网页中使用矢量图形变得更加方便,而无需依赖于图片文件。

本地存储:提供了本地存储功能,包括 localStorage sessionStorage,允许网页在客户端存储数据

表单控件的改进:引入了新的表单控件,如<input type="date">、<input type="email">、<input type="url">等,同时还增强了表单验证和输入限制的功能。

拖放 API: 提供了原生的拖放 API,使得开发者可以更轻松地实现拖放操作,包括拖放文件、文本或者其他元素。

Web Workers: 允许通过Web Workers在后台运行JavaScript代码,以提高网页的性能和响应速度,避免阻塞主线程。

WebSocket: 引入了 WebSocket 技术,允许在客户端和服务器之间建立持久的全双工连接,以实现实时通信。

响应式设计和媒体查询:使得响应式网页设计更加容易实现,通过媒体查询可以根据设备的特性(如屏幕尺寸、分辨率等)调整页面布局和样式。


3. 对HTML语义化理解

  • 提高可读性: 使用语义化标签可以使代码更加易于阅读和理解。
  • 增强可维护性: 语义化的 HTML 代码具有良好的结构,易于维护和修改。
  • 提升可访问性: 语义化的 HTML 代码有助于网页的可访问性,使得使用屏幕阅读器等辅助技术的人们能够更好地理解和浏览网页内容。
  • SEO 优化: 使用语义化标签可以帮助搜索引擎更好地理解网页的内容结构和关键信息
  • 跨平台兼容性: 语义化的 HTML 代码可以更好地适应不同的浏览器和设备,提供一致的用户体验。即使在没有 CSS 样式的情况下,页面的结构和内容仍然具备一定的可读性和可用性。

4. DOCTYPE(文档类型) 的作用

  • 告知浏览器使用哪种 HTML 或 XHTML 规范解析文档: 告知浏览器使用哪种标准解析 HTML 文档,以确保浏览器能够正确地渲染文档。不同的文档类型可能会影响浏览器的解析方式和渲染效果。

  • 触发标准模式Standards Mode):帮助浏览器确定文档使用的是标准模式还是混杂模式(Quirks Mode)。标准模式会按照规范的要求来解析和渲染文档,而混杂模式则会模拟旧版浏览器的行为,可能导致兼容性问题和渲染不一致性。

  • 帮助验证文档的正确性:可以帮助开发者验证 HTML 文档的正确性,确保文档符合相应的标准和规范。如果文档缺少或者错误地声明了文档类型,可能会导致浏览器的解析错误或渲染问题。

  • 指定浏览器的渲染模式:还可以影响浏览器的渲染模式,比如是否启用怪异模式(Quirks Mode)、几乎标准模式(Almost Standards Mode)或者严格模式(Strict Mode)。这些模式会影响浏览器对 CSSJavaScript 的解析和执行方式。

5. iframe的缺点和优点

优点:

  • 内容隔离:可以将另一个 HTML 文档嵌入到当前文档中,实现内容的隔离。这意味着嵌入的文档可以独立于主文档进行加载和处理,从而避免相互之间的影响。

  • 实现页面模块化: 可以将页面划分为多个独立的模块,每个模块可以单独加载和处理,有助于提高代码的可维护性和可重用性。

  • 跨域通信:允许在不同域名之间进行通信,可以实现跨域数据传输和交互。

  • 加载异步内容:允许在主页面加载完成后再加载嵌入的内容,加快页面的加载速度

  • 提供安全沙箱环境:具有安全沙箱环境,可以限制嵌入内容对主页面的访问权限,防止恶意代码的执行。

缺点:

  • 性能开销: 会增加页面的加载时间和内存占用,特别是当嵌入的内容较大或嵌套层级较深时,会导致性能下降。

  • 可访问性问题: 内容可能无法被搜索引擎检索到,也可能无法被屏幕阅读器等辅助技术正确解析。

  • 导航问题: 如果嵌入的页面包含导航功能,用户在子页面进行的导航操作可能会影响整个页面的导航状态,用户体验不佳。

  • 安全风险:可能会被用于加载恶意内容或进行跨站脚本攻击(XSS)。

  • 不利于响应式布局:内容可能无法适应不同设备的屏幕尺寸,不利于实现响应式布局和移动端优化。

6. Canvas和SVG的区别

Canvas(画布):

基于像素: Canvas 是基于像素的绘图方式,它通过 JavaScript 脚本绘制图形,并以像素为单位进行操作。每次绘制都是直接操作像素,因此适用于动态、复杂的图形和动画效果。

绘图 API: Canvas 提供了一系列的绘图 API,如绘制路径、矩形、圆形、文本等

不可缩放: Canvas 中绘制的图形是基于像素的,因此不支持图形的无损缩放。当页面缩放时,可能导致图像失真或模糊。

动态更新: Canvas 提供了动态更新图形的能力

由于 Canvas 具有高性能和动态更新的特点,适合用于开发游戏、图表和数据可视化等需要实时更新和交互的场景。

SVG(可缩放矢量图形):

基于矢量: SVG 是基于矢量的图形绘制方式,它使用 XML 格式描述图形,可以无损地进行缩放和变换。因此,SVG 适合用于制作各种分辨率和大小的图形。

绘图元素: SVG 提供了一系列的绘图元素,如 <rect>(矩形)、<circle>(圆形)、<path>(路径)等,开发者可以直接在 HTML 文档中使用这些元素来描述图形。

支持CSS样式: SVG 支持使用 CSS 来控制图形的样式和动画

文本渲染: SVG 支持文本的渲染和布局,可以在图形中添加文本标签,并对文本进行样式控制和布局调整。

静态图形: SVG 中的图形是静态的,一旦绘制完成后就无法通过 JavaScript 动态更新,需要通过重新绘制来实现图形的变化。

适用于图标、图形设计等需求: 由于 SVG 具有无损缩放和矢量特性,适合用于制作图标、图形设计和响应式布局等需要适应不同尺寸和分辨率的场景。

Canvas 适用于动态、复杂的图形和动画效果,而
SVG 适用于静态、可缩放的矢量图形和图标设计等场景。

7. script标签中defer和async的区别

defer 和 async 是两个用于控制脚本加载和执行顺序的属性
他俩都是表示异步加载外部JS脚本,不会阻碍页面的加载解析。
区别:

区别defer属性async属性
当浏览器遇到带有 defer 属性的<script>标签时,会立即开始下载脚本文件,不会立即执行。脚本会在文档解析完毕后按照文档中的顺序依次执行,即在 DOMContentLoaded 事件触发前执行。当浏览器遇到带有 async 属性的 <script> 标签时,立即开始下载脚本文件,不会阻塞 HTML 解析过程。一旦脚本文件下载完成,会立即执行,不会按照它们在文档中的顺序执行。
多个脚本文件可以并行下载,按文档中的顺序依次执行。多个脚本文件可以并行下载,下载完成后立即执行,不按文档中的顺序执行
保证脚本在 DOMContentLoaded 事件触发前执行,因此适合用于需要在 DOMContentLoaded 事件触发前执行的脚本,如初始化页面的 JavaScript 代码。async属性的脚本可能在 DOMContentLoaded 事件触发前或之后执行,具体取决于脚本文件的加载和执行时间。

如果需要保证脚本的执行顺序或依赖关系,应该使用 defer 属性
如果脚本之间没有依赖关系,并且希望提高页面加载性能,可以考虑使用 async 属性。

8. 行内元素、块级元素、空(void)

在 HTML 中,元素可以根据它们的显示特性分为三种主要类型:
行内元素、块级元素和空(void)元素。

  • 行内元素在显示时不会打断文本流,通常只占据其内容的宽度。例如:<span>、<a>、<img>、<strong>、<em> 等。
  • 块级元素会在页面上以块的形式显示,通常会打断文本流并占据一整行(或者一整块)的空间。例如:<div>、<p>、<h1>-<h6>、<ul>、<li>
  • 空元素也被称为无内容元素或自闭合元素,它们不包含任何内容或者子元素。
    空元素在 HTML 中通常是没有闭合标签的元素,例如:<img>、<br>、<input>、<meta> 等。
    空元素在 HTML5 中可以使用自闭合标签形式,例如 <br/> 或者 <input/>

9. 怎样添加、移除、移动、复制、创建和查找节点

添加节点document.appendChild(dom)
移除节点document.removeChild(dom)
移动节点document.appendChild(targetDom)
复制节点dom.cloneNode(true),参数true表示是否复制子节点
创建节点document.createElement(dom)
查找节点:
document.getElementById("elementId")
document.getElementsByClassName("className")
document.getElementsByTagName("tagName")
document.querySelector("selector")
document.querySelectorAll("selector")

10.前端页面优化的解决方案

  • 网页内容优化:
    懒加载数据,避免重定向,iframe少使用,使用雪碧图(精灵图),要有网站小图标,使用canvas压缩图片
  • CSS优化:
    避免使用@import,样式表放在head里面,避免使用css表达式
  • js优化
    减少DOM访问,脚本放底部,合理使用节流函数和防抖函数

11.HTML5新特性

语义标签,增强型表单,视频和音频,Canvas绘图,SVG绘图,地理定位,拖放API,WebWorker,WebStorage,WebSocket

12.


二、CSS

1. CSS3新增特性

  • 选择器的增强:属性选择器和伪类选择器的增强
  • 盒子模型的改进:圆角边框,阴影,
  • 渐变:线性渐变,径向渐变
  • 过渡和动画效果
  • 线性渐变(linear-gradient): 允许创建两种或更多种颜色之间的渐变效果,可以沿着水平、垂直或对角线方向应用。
  • 径向渐变(radial-gradient): 允许创建颜色从一个中心点向外辐射的渐变效果。
  • 过渡(Transitions)和动画(Animations):
  • 媒体查询(Media Queries):响应式设计
  • 变换(Transforms)和过滤(Filters)
  • 等等

2.盒模型

在这里插入图片描述

盒子模型是指在网页设计中,每个元素都被看作一个矩形的盒子,包括内容区域、内边距、边框和外边距。这些组成部分围绕着元素的内容(content)而存在。CSS3 在盒子模型方面做了一些改进,主要包括以下几个方面:

  • 内容区域(Content Area):
    表示元素实际包含的内容,如文本、图像等。内容区域的大小可以通过设置元素的宽度(width)和高度(height)属性来控制。
  • 内边距(Padding):
    内边距是内容区域与边框之间的空间,可以通过设置 padding 属性来调整。

CSS3 中可以使用更灵活的单位(如 em、rem)来设置内边距,使得布局更加灵活和可维护。

  • 边框(Border):
    边框是围绕内容和内边距的线条,可以通过设置 border 属性来控制。

CSS3 引入了新的边框样式(如圆角边框)、边框阴影等特性,使得边框的设计更加丰富多样。

  • 外边距(Margin):
    外边距是元素与相邻元素之间的空间,可以通过设置 margin 属性来调整,可以用来控制元素之间的间距,实现页面布局的调整和排列。

3.CSS选择器都有哪些?

  • 元素选择器(Element Selector): 选择指定 HTML 元素。例如,p 选择所有 <p> 元素。
  • ID 选择器(ID Selector): 选择具有特定 id 属性的元素。以#符号开头,后跟id值。例如,#header 选择 id 为 “header” 的元素。
  • 类选择器(Class Selector): 选择具有特定 class 属性的元素。以.符号开头,后跟 class 名称。例如,.btn 选择所有 class"btn"的元素。
  • 属性选择器(Attribute Selector): 选择具有特定属性的元素。可以根据属性名和属性值进行选择。例如,[type="text"] 选择所有 type 属性值为"text"的元素。
  • 后代选择器(Descendant Selector): 选择元素的后代元素。用空格分隔父元素和后代元素。例如,div p选择所有在 <div> 元素内部的<p>元素。
  • 子元素选择器(Child Selector): 选择元素的直接子元素。使用 > 符号。例如,ul > li 选择所有直接作为 <ul> 元素子元素的 <li> 元素。
  • 相邻兄弟选择器(Adjacent Sibling Selector): 选择紧接在另一个元素后的元素。使用 + 符号。例如,h2 + p 选择紧跟在 <h2> 元素后的 <p> 元素。
  • 通用选择器(Universal Selector): 选择所有元素。用 * 表示。例如,* 选择页面上的所有元素。
  • 伪类选择器(Pseudo-class Selector): 选择元素的特定状态或位置。以 : 开头,后跟伪类名称。例如,:hover 选择鼠标悬停在元素上时的状态。
  • 伪元素选择器(Pseudo-element Selector): 用于向某些选择器添加特殊的效果。以 :: 开头,后跟伪元素名称。例如,::before 在元素内容之前插入内容。

4. CSS可继承属性和不可继承属性

CSS 属性可以分为可继承属性和不可继承属性。
可继承属性是指当应用到父元素时,它们会自动应用到其后代元素。而不可继承属性则不会。

  • 可继承属性:

字体相关属性:例如 font-family、font-size、font-weight、font-style 等。
文本相关属性:例如 color、line-height、text-align、text-decoration 等。
列表相关属性:例如 list-style-type、list-style-position、list-style-image 等。
表格相关属性:例如 border-collapse、border-spacing、caption-side 等。
其他:例如 visibility、cursor、opacity 等。

  • 不可继承属性:

盒子模型相关属性:例如 width、height、margin、padding 等。
定位相关属性:例如 position、top、right、bottom、left 等。
边框相关属性:例如 border-width、border-style、border-color 等。
背景相关属性:例如 background-color、background-image、background-position 等。
其他:例如 display、overflow、z-index 等。

5.dislpay的属性和作用

属性作用
block块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
inline行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
flexflex容器布局
table块级表格
none隐藏元素
inherit从父类继承display属性
inline-block行内块级元素,默认宽度为内容宽度,可以设置宽高,同行显示

6. CSS隐藏元素的方式

display: none;
这是最彻底的隐藏方式,它会完全移除元素,包括它所占据的空间。这意味着元素对布局不会产生任何影响。

visibility: hidden;
这种方式会隐藏元素,但元素仍然占据布局空间。即使元素不可见,它仍然会占据和它原本位置相同的空间。

opacity: 0;
使用 opacity 属性将元素的不透明度设置为 0,使其完全透明,但仍然会保留其布局空间。

position: absolute;
将元素定位到屏幕外,这样它就不会在页面上显示,但仍然会占据布局空间。

clip-path: inset(100%);
使用 clip-path 将元素裁剪掉,这样它就不会在页面上显示,但仍然会占据布局空间。

transform: scale(0);
使用 transform 缩放元素到 0 大小,使其不可见,但仍然会占据布局空间。

7.单行、多行文本溢出的解决办法

单行文本:
可以使用 text-overflow 属性来控制文本溢出时的显示方式,并配合 white-space 和 overflow 属性来实现。通常使用的方式是将 white-space 设置为 nowrap,以防止文本换行,然后将 overflow 设置为 hidden,当文本溢出时,使用 text-overflow 来指定溢出时的显示方式。

.single-line-text {
    white-space: nowrap; /* 防止文本换行 */
    overflow: hidden; /* 溢出隐藏 */
    text-overflow: ellipsis; /* 溢出时显示省略号 */
}

多行文本:
常见的解决办法是使用 CSS3 的 -webkit-line-clamp 属性,它可以指定在多行文本溢出时显示的行数,并配合 display: -webkit-box 和 -webkit-box-orient 来实现。

.multi-line-text {
    overflow: hidden; /* 溢出隐藏 */
    display: -webkit-box; /* 将元素作为弹性伸缩盒子 */
    -webkit-box-orient: vertical; /* 设置盒子内子元素的排列方式为垂直方向 */
    -webkit-line-clamp: 3; /* 显示的行数 */
}

8.Sass、Less的区别是什么?

Sass(Syntactically Awesome Style Sheets)和 Less(Leaner Style Sheets)都是一种预处理器,用于增强 CSS 的功能并提供更便捷的开发体验。它们之间的区别主要体现在语法、功能和生态系统等方面

区别Sasscss
语法Sass 使用缩进式的语法(类似于 Python),并使用 .scss 扩展名。它更接近于常规的 CSS 语法,可以很容易地将现有的 CSS 代码转换为 SassLess 使用类似于 CSS的语法,但添加了一些额外的功能,如变量和混合器。Less 文件通常使用 .less 扩展名。
功能Sass 提供了更多的功能,如嵌套规则、变量、混合器、继承等。这些功能使得 Sass 更强大和灵活。Less 也提供了类似的功能,但相对较少,例如变量、混合器和嵌套规则。
生态系统 Sass 拥有更广泛和更成熟的生态系统,包括大量的第三方库和工具,如Compass、Bourbon等,以及与框架的深度集成,如 Bootstrap。Less 的生态系统相对较小,但仍然有一些流行的库和工具可供使用。
编译方式Sass 使用 Ruby 编写,可以通过命令行或构建工具进行编译Less 使用 JavaScript 编写,可以通过 Node.js 或浏览器插件进行编译。

9.link和@import的区别是什么?

<link> 标签和 @import 指令都用于在 HTML 或 CSS 文件中引入外部资源(如样式表)

区别link@import
使用位置<link> 标签可以在 HTML<head> 部分或文档的任何位置使用,用于引入外部 CSS 文件。它是 HTML 的标签,不仅可以加载样式表,还可以加载其他资源@import 指令是CSS的一部分,只能在CSS文件中使用,用于在样式表中引入其他样式表。通常,@import 指令会在样式表的顶部使用。
加载时机 ` 标签会在页面加载时同时加载外部资源(如 CSS` 文件),不会阻塞页面的加载。@import 指令会在 CSS 文件加载完毕后再去加载被引入的外部资源,这会导致页面加载时出现阻塞,影响页面的性能和加载速度。
兼容性<link> 标签具有更好的浏览器兼容性,适用于所有主流浏览器。@import 指令在较早的浏览器中可能存在兼容性问题,尤其是在嵌套使用时,会导致某些浏览器无法正确解析样式表。

<link> 标签引入的样式表具有比 @import 引入的样式表更高的优先级,因此在样式冲突时,<link> 引入的样式表会覆盖 @import 引入的样式表。

10.常见的CSS单位?

px,%,em,rem,vw,vh(视图窗口的宽高)

px,em,rem的区别:
px 固定像素单位,不能随其它元素的变化而变化
em是相对于父元素的单位,会随着父元素变化而变化
rem是相对于根元素html,它会随着html元素变化而变化

11.两栏、三栏布局

11.1 两栏布局

指将网页内容分为两个主要的列,通常是左侧栏和右侧栏。这种布局常用于博客、新闻和产品页面等。
实现两栏布局的方法有多种,以下是其中两种常见的方式:

浮动布局

HTML 结构:使用<div>元素创建左侧栏和右侧栏的容器。

<div class="container">
  <div class="left-column">左侧栏内容</div>
  <div class="right-column">右侧栏内容</div>
</div>

CSS 样式:使用 float 属性将左侧栏浮动到左侧,设置右侧栏的margin-left属性为左侧栏的宽度,使其位于右侧。

.left-column {
  float: left;
  width: 30%; /* 左侧栏宽度 */
  background-color: aqua;  /*蓝色*/
}

.right-column {
  margin-left: 30%; /* 左侧栏的宽度 */
  background-color: bisque;/*黄色*/
}

在这里插入图片描述

Flexbox 布局
HTML 结构:同样使用 <div> 元素创建左侧栏和右侧栏的容器。

<div class="container">
  <div class="left-column">左侧栏内容</div>
  <div class="right-column">右侧栏内容</div>
</div>

CSS 样式:使用 Flexbox 布局,将容器设置为 display: flex;,然后通过 flex-basis flex-grow属性控制左右两栏的宽度比例。

.container {
  display: flex;
}

.left-column {
  flex-basis: 30%; /* 左侧栏宽度 */
}

.right-column {
  flex-grow: 1; /* 右侧栏自适应宽度 */
}

以上是两种常见的实现两栏布局的方法,具体选择哪种方式取决于项目需求和个人喜好。
同时,还可以结合其他布局技术(如 Grid 布局)来实现更复杂的布局效果。

11.2三栏布局

实现三栏布局同样有多种方法,以下是两种常见的方式:

浮动布局
HTML 结构:使用 <div> 元素创建左侧栏、中间栏和右侧栏的容器。

<div class="container">
  <div class="left-column">左侧栏内容</div>
  <div class="right-column">右侧栏内容</div>
</div>

CSS 样式:使用 float 属性将左侧栏和右侧栏浮动到左侧和右侧,设置中间栏的 margin-leftmargin-right 属性为左侧栏和右侧栏的宽度,使其位于中间。

.left-column {
  float: left;
  width: 30%; /* 左侧栏宽度 */
}

.right-column {
  float: right;
  width: 30%; /* 右侧栏宽度 */
}

Flexbox 布局

HTML 结构:同样使用 <div> 元素创建左侧栏、中间栏和右侧栏的容器。

<div class="container">
  <div class="left-column">左侧栏内容</div>
  <div class="middle-column">中间栏内容</div>
  <div class="right-column">右侧栏内容</div>
</div>

CSS 样式:使用Flexbox布局,将容器设置为 display: flex;,然后通过flex-basisflex-grow 属性控制左右两栏的宽度比例。

.container {
  display: flex;
  background-color: aqua;
}

.left-column, .right-column {
  flex-basis: 30%; /* 左右侧栏宽度 */
  background-color: yellow;
}

.middle-column {
  flex-grow: 1; /* 中间栏自适应宽度 */
  background-color: blueviolet;
}

在这里插入图片描述

12.BFC是什么?如何创建?

BFC是块级格式上下文(Block Formatting Context,BFC),是CSS布局的一个概念,在BFC布局里面的元素不受外面元素影响

常见的创建方式

  • 根元素或包含根元素的元素。
  • 浮动元素(元素的 float 不是 none)。
  • 绝对定位元素(元素的position absolutefixed)。
  • 行内块元素(元素的 display inline-block)。
  • 表格单元格(元素的 display table-cellHTML 表格单元格默认为 BFC)。
  • overflow 值不为 visible(元素的 overflow hiddenautoscroll)。

作用

  • 清除浮动:BFC 可以包含浮动元素并阻止其影响到外部元素。
  • 防止边距重叠:属于同一个 BFC 的两个相邻元素的上下外边距不会发生重叠。
  • 自适应高度:BFC 可以包含浮动元素并撑开父元素的高度。
  • 防止浮动元素覆盖:BFC 可以防止浮动元素覆盖到其后面的元素。

13.margin重叠的解决办法

两个相邻元素的上下外边距发生重叠,垂直方向才会发生这种情况

  • 使用边框或填充:在两个相邻元素之间添加一个边框或者内边距(padding)
    border-bottom: 1px solid transparent; /* 添加边框,两个元素都要加 */
  • 使用定位:通过为其中一个元素设置定位,将其脱离文档流,从而避免边距重叠。
    position: relative; /* 或者设置为 absolute 或 fixed */
  • 使用清除浮动技术:如果边距重叠是由浮动元素引起的,可以使用清除浮动的技术来解决。
.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

.float-element {
  float: left;
}

.normal-element {
  margin-top: 30px;
}
  • 使用 display: flow-root:将包含元素的父元素设置为 display: flow-root,可以创建新的 BFC,从而避免边距重叠。
    .parent-element { display: flow-root; }

外边距重叠的计算规则
两正取大 10px :20px ?取20px
两负取绝对值大 -10px : -20px ? 取-20px
一正一负两者相加 10px : -20px ? 取-10px
一个元素的外边距与其父元素的外边距重叠,取较大值。
一个元素的外边距与其子元素的外边距重叠,取较大值。

14. 元素定位position常用取值?

  • static(默认值):无定位,元素正常在文档流显示。
  • relative:相对定位,相对于原位置定位
  • absolute:绝对定位,元素相对于其最近的非 static 祖先元素进行定位,如果没有则相对于初始包含块(通常是文档的根元素)。
  • fixed:绝对定位,页面滚动元素的位置也不会改变,相对于窗口。
  • sticky:粘性定位,基于用户滚动位置

15 1px的问题

1px 问题" 是指在某些设备上或者某些浏览器中,以物理像素为单位的细线可能看起来过于模糊或者不清晰,特别是在高分辨率的屏幕上。

这个问题通常在使用 CSS 进行绘制细线或者边框时出现。
当你使用 CSS 设置一个 1px 的边框或者细线时,看起来变粗不止1px

解决方法

  • 设置为 0.5px 或者 0.3333px 。
  • 在某些情况下,使用 em、rem 或者 vw/vh 等相对单位来代替像素单位,可以避免 “1px 问题”
  • 可以使用伪元素::before或者 ::after 来创建细线,然后对其进行缩放以适应所需的宽度。这种方法可以确保在各种设备上都能得到清晰的效果。
  • CSS3 提供了一些边框样式,如 border-image,可以用来创建精细的边框效果,而不会受到物理像素的限制。

16. 浮动塌陷的解决办法

  • 开启BFC 具体看 第12 条
  • 在浮动元素后添加元素,并设置其clear属性
  • 使用 Flexbox 布局:使用 Flexbox 布局可以非常轻松地解决浮动造成的布局问题,而无需清除浮动。通过将父元素设置为 display: flex;,父元素将自动包含其内部的浮动元素。
  • 清除浮动(Clearfix):清除浮动是最常见的解决方法之一。您可以在父元素的样式中添加一个清除浮动的伪元素,以确保父元素能够正确地包含其内部的浮动元素。

17.前端常见的布局方式

  • 静态布局
    态布局是最基础的布局方式,元素的位置和尺寸使用固定的像素值px来定义,不随浏览器窗口大小的改变而改变。
  • 弹性布局flex
    Flexbox 是一种用于排列、对齐和分配空间的新型布局方式。通过在容器上应用 `display: flex;,可以创建一个弹性容器,其中的子元素可以根据需要调整其大小和顺序,以填充可用空间。
  • 自适应布局bootstrap
    Bootstrap 是一个流行的前端框架,提供了一套基于栅格系统的自适应布局工具。使用 Bootstrap,您可以轻松地创建响应式网页布局,根据设备的不同尺寸自动调整布局和样式。
  • 流式布局fluid
    流式布局是一种相对于浏览器窗口大小而自动调整的布局方式。与静态布局不同,流式布局使用百分比单位来定义尺寸,使得元素可以根据浏览器窗口的大小进行缩放和调整。
  • 响应式布局
    响应式布局是一种结合了流式布局和媒体查询的布局方式,旨在使网页在不同设备上都能提供最佳的用户体验。通过使用媒体查询,可以根据设备的屏幕尺寸、分辨率和方向等特性,为不同情况下的布局应用不同的样式和排列方式。
  • 浮动布局
    浮动布局是一种基于浮动属性的布局方式,通常用于实现多列布局。通过将元素浮动到左侧或右侧,可以使其脱离文档流,并让其他内容环绕其周围。但是需要注意,浮动布局可能会导致父元素的高度塌陷问题,需要额外的处理来解决。
  • 定位布局
    定位布局是一种通过定位属性(如 position: absolute; position: relative;)来控制元素位置的布局方式。通过设置元素的位置和层叠顺序,可以实现精确的布局效果,但需要谨慎使用,以免出现布局混乱或覆盖的问题。

三、JavaScript

1.js的基本数据类型

基本数据类型:字符串 (String)、数字 (Number)、布尔值 (Boolean)、空值 (Null)、未定义 (Undefined)、符号 (Symbol)
引用数据类型:对象 (Object)、数组(Array)、函数(Function)

存储方式:基本数据类型存在里,引用数据类型存在

2.null和undefined有什么区别?

undefined:表示变量声明了但尚未被赋值,或者访问对象属性时,该属性不存在,typeof为undefined。
null:表示一个空值或者无值的对象,typeof为object

3.instanceof 运算符的实现原理及实现

instanceof运算符适用于检测构造函数的prototype属性上是否出现在某个实例对象的原型链上
实现原理
instanceof 运算符的原理是基于原型链的查找。当使用 obj instanceof Constructor 进行判断时,JavaScript 引擎会从 obj 的原型链上查找 Constructor.prototype 是否存在,如果存在则返回 true,否则继续在原型链上查找。如果查找到原型链的顶端仍然没有找到,则返回 false。

instanceof运算符只能用于检查某个对象是否是某个构造函数的实例,不能用于基本类型的检查,如string、number等

4. typeof 和 instanceof 区别

typeof 和 instanceof 是 JavaScript 中用于检查变量类型的两种不同操作符。

typeofinstanceof
typeof 是一个操作符,用于检查变量的数据类型instanceof 是一个运算符,用于检查对象的构造函数
返回一个字符串,表示变量的数据类型返回一个布尔值,表示对象是否属于某个构造函数的实例。
检查基本数据类型,无法判断引用数据类型主要用于检查对象是否属于某个特定类型的实例,通常是自定义对象的类型。不能正确判断基本数据类型

对于 null 返回 “object”。这是 JavaScript 的一个历史遗留问题。
对于基本数据类型和函数,typeof 运算符返回以下字符串:
“undefined”:未定义的值
“boolean”:布尔值;
“number”:数值
“string”:字符串
“symbol”:Symbol 类型
“bigint”:BigInt 类型
“function”:函数

5. 0.1+0.2 !==0.3 ????

因为 JavaScript 中的数字都是以双精度浮点数的形式存储,而双精度浮点数无法精确表示某些十进制小数
0.1 + 0.2; // 0.30000000000000004
解决办法之一:转换为整数进行计算: 将浮点数转换为整数进行计算,然后再将结果转换回浮点数。
在这里插入图片描述

6. 判断对象是数组的方式有哪些?

  • 使用 Array.isArray() 方法: 这是最常用和推荐的方法
    Array.isArray(arr)
  • 使用instanceof 操作符
    arr instanceof Array
  • 使用对象的 constructor 属性
    (arr.constructor === Array
  • 使用对象原型链: 可以检查对象的原型链中是否包含Array.prototype
    arr.__proto__ === Array.prototype
  • 使用 Object.prototype.toString.call() 方法
    Object.prototype.toString.call(arr) === '[object Array]'

7.什么是类数组?如何转化为数组

类数组:具有数字索引和 length 属性,但不具备数组对象的方法。常见的类数组对象包括函数的 arguments 对象、DOM 元素集合(例如通过 document.querySelectorAll() 获取的元素列表)
转化方法

  • Array.from() 方法
    var arr = Array.from(arrayLike)
  • Array.prototype.slice.call() 方法
    var arr = Array.prototype.slice.call(arrayLike);
  • 使用展开运算符(Spread Operator)
    var arr = [...arrayLike];
  • 使用 Array.prototype.concat() 方法
    var arr = Array.prototype.concat.call([], arrayLike);

8.数组有哪些原生方法?

push(),pop(),shift(),unshift(),splice(),concat(),slice(),indexof()等等

9.substring和substr的区别是什么?

都是截取字符串一部分,只是参数不同。第二个参数可选,为空默认截取到最后。substr() 中的索引可以是负数,表示从字符串末尾开始计算。
substring(startIndex, endIndex) (开始索引,结束索引)
substr(startIndex, length)(开始索引,长度)

10.object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别是什么?

在对象操作中都执行浅拷贝

  • Object.assign() 方法用于将一个或多个源对象的可枚举属性复制到目标对象,并返回目标对象。如果目标对象是一个空对象,则相当于创建了源对象的一个副本。
const target = { a: 1, b: 2 };
const source = { b: 3, c: 4 };
const result = Object.assign(target, source);
  • 扩展运算符(…)通常用于将数组或对象展开成多个参数或元素。在对象上使用扩展运算符时,它会复制对象的所有可枚举属性到新的对象中。
const mergedObject = { ...obj1, ...obj2 };
区别object.assign
修改目标对象创建一个新的对象
是一个函数,需要传递目标对象和一个或多个源对象作为参数扩展运算符是一种语法,通常用于创建新的对象或数组。
处理嵌套对象时,扩展运算符可以更方便地实现深拷贝处理嵌套对象时Object.assign() 需要额外的操作来处理深层次的属性

11.new的实现原理和步骤?

  • 创建一个空对象(即 {})。
  • 将新对象的原型指向构造函数的 prototype 属性。
  • 将步骤1中创建的空对象作为this上下文。
  • 执行构造函数,同时将this绑定到新创建的对象。
  • 如果构造函数没有显式返回一个对象,则返回步骤1创建的新对象。如果构造函数返回的是一个对象,则返回该对象。
// 构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
}
// 使用 new 关键字创建实例
const person1 = new Person('Alice', 30);

// 上述步骤可以理解为类似于以下代码的执行过程:

// 步骤1:创建一个空的简单JavaScript对象
const newObject = {};

// 步骤2:将新对象的原型链接到构造函数的原型对象
newObject.__proto__ = Person.prototype;

// 步骤3和步骤4:执行构造函数,同时将 this 绑定到新创建的对象
Person.call(newObject, 'Alice', 30);

// 步骤5:返回新对象
const person2 = newObject;

12.for…in和for…of的区别?

for…in 和 for…of 是 JavaScript 中两种不同的循环语句
它们的主要区别在于遍历的对象和可迭代的数据类型。

  • for…of 遍历获取的是对象的键值,for…in 获取对象的键名;
  • for… in 会遍历对象的整个原型链,性能差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链;

for…in 循环遍历对象
for…of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象

13.如何理解Ajax,实现步骤是什么样的?

Ajax是一种在无需重新加载整个网页的情况下,能够实现与服务器进行数据交换的技术。
步骤:

  • 创建 XMLHttpRequest 对象
    const xhr = new XMLHttpRequest();
  • 写入基本信息:请求类型、URL、是否异步
    xhr.open('GET', 'https://example.com/data', true);
  • 设置请求头(可选,如果要特定的请求头)
    xhr.setRequestHeader('Content-Type', 'application/json');
  • 使用 XMLHttpRequest 对象的 send() 方法发送请求,有数据要记得写入数据
    xhr.send();
  • 处理响应:当收到来自服务器的响应时,会触发 XMLHttpRequest 对象的 onreadystatechange 事件。在事件处理程序中,可以通过检查 xhr.readyState 和 xhr.status 来确定请求的状态,并获取响应数据。
xhr.onreadystatechange = function() {
    if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status === 200) {
            console.log(xhr.responseText);  // 响应数据
        } else {
            console.error('请求失败');
        }
    }
};

14.Ajax、Axios、Fetch的区别?

  • Ajax:Ajax 是一种使用 XMLHttpRequest 对象进行异步通信的技术,优势在于它是浏览器原生支持的技术,不需要额外的库或依赖,适用于简单的异步请求。兼容性良好,实现代码量相比较偏多。不需要额外依赖。
  • Axios:是一个基于 PromiseHTTP 客户端,可以在浏览器和 Node.js 中使用,用于发起 HTTP 请求。提供了更简洁和易用的 API,支持拦截请求和响应,可以全局配置请求等。具有更好的错误处理机制,并且自动将响应数据转换为 JSON 格式。扩展性好
  • Fetch:浏览器提供的用于发起网络请求的 API,它是用于替代XMLHttpRequest的新标准,基于 Promise,支持流式操作、请求和响应的拦截等特性,不会自动发送跨域凭证,需要手动设置,不需要额外依赖。

15.forEach和map方法有什么区别?

作用是遍历数组中的每个元素并对其执行指定的操作

区别forEachmap
返回值没有返回值(或者说返回值是 undefined)。它只是对数组中的每个元素执行指定的操作,但不会返回新的数组返回一个新数组,该数组由对原数组中的每个元素调用提供的函数得到的返回值组成。
对原数组的影响不会改变原数组不会改变原数组,但它会返回一个新的数组
使用场景适合在循环数组时执行一些操作,例如打印数组元素、修改数组元素等适合在需要对数组中的每个元素进行操作并生成新数组时使用,例如将数组中的每个元素加倍、转换为另一种格式等
// forEach 示例
const array = [1, 2, 3, 4, 5];
array.forEach(element => {
    console.log(element); // 打印数组中的每个元素
});

// map 示例
const doubledArray = array.map(element => {
    return element * 2; // 将数组中的每个元素加倍并生成新数组
});
console.log(doubledArray); // 打印新数组

16.深浅拷贝的理解和实现

浅拷贝(Shallow Copy)
浅拷贝是指创建一个新的数据结构,新的数据结构中的元素是原始数据结构中的引用。换句话说,浅拷贝只会复制原始数据结构的第一层,而不会递归复制所有嵌套的数据结构。
实现方式:

  • 使用扩展运算符 (…) 或 Object.assign()
const originalArray = [1, 2, 3];
const shallowCopy = [...originalArray]; // 或者 Object.assign([], originalArray);
  • 使用数组的 slice() 方法
const originalArray = [1, 2, 3];
const shallowCopy = originalArray.slice();
  • 使用对象的 Object.assign() 方法
const originalObject = { a: 1, b: 2 };
const shallowCopy = Object.assign({}, originalObject);

深拷贝(Deep Copy)
深拷贝是指创建一个新的数据结构,并递归复制原始数据结构中的所有嵌套数据结构,使得新的数据结构与原始数据结构完全独立,修改新的数据结构不会影响到原始数据结构。

实现方式:

  • 使用递归:递归遍历原始数据结构,针对每一层嵌套的数据结构进行拷贝。
function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj; // 如果是基本类型或者 null,则直接返回
    }

    let copy;

    if (Array.isArray(obj)) {
        copy = [];
        for (let i = 0; i < obj.length; i++) {
            copy[i] = deepCopy(obj[i]); // 递归拷贝数组中的每个元素
        }
    } else {
        copy = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                copy[key] = deepCopy(obj[key]); // 递归拷贝对象中的每个属性值
            }
        }
    }
    return copy;
}

const originalObject = { a: { b: 1 }, c: [2, 3] };
const deepCopyObject = deepCopy(originalObject);
  • 使用 JSON 序列化和反序列化:将原始数据结构转换为 JSON字符串,再将其解析为 JavaScript` 对象。
const originalObject = { a: { b: 1 }, c: [2, 3] };
const deepCopyObject = JSON.parse(JSON.stringify(originalObject));

注意事项:
对于浅拷贝,如果原始数据结构中包含引用类型(如对象、数组等),复制后的数据结构中的这些引用类型元素仍然会指向同一个内存地址,因此对其中一个引用类型元素的修改会影响到另一个。
对于深拷贝,由于递归复制了所有嵌套数据结构,因此新的数据结构中的引用类型元素与原始数据结构中的对应元素完全独立,修改新的数据结构不会影响到原始数据结构。
使用 JSON 序列化和反序列化进行深拷贝时,注意原始数据结构中不能包含循环引用,否则会导致无限递归。

17.实现继承的几种方式

  • 原型链继承 :父类的实例作为子类的原型
    Woman.prototype= new People();
  • 借用构造函数继承(伪造对象、经典继承)
    People.call(this); //People.call(this,'wangxiaoxia');
  • 实例继承(原型式继承)
function Wonman(name){
  let instance = new People();
  instance.name = name || 'wangxiaoxia';
  return instance;
}
let wonmanObj = new Wonman();

18. 前端缓存(数据持久化)的理解

前端缓存是指将网页资源(如 HTML、CSS、JavaScript、图像等)保存在客户端(通常是用户的浏览器)中的一种技术。分为浏览器缓存HTTP缓存

前端主要在 发起请求、后端处理、浏览器响应的一三步骤优化性能

常见的缓存策略包括:强缓存(通过设置 ExpiresCache-Control 头来指定资源的过期时间)、协商缓存(通过验证资源的 ETagLast-Modified 时间来确定是否需要重新加载资源)、离线缓存(通过使用 Service Worker 技术将资源保存在本地,以便在离线状态下访问)

强制缓存的情况主要有三种,如下:
①不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求
②存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
③存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果

协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
协商缓存生效返回304,失效返回200和请求结果

19.解释一下防抖和节流

防抖debounce:事件触发后,等待一个固定的时间间隔(称为延迟时间),时间间隔内未再次触发该事件,才执行函数。搜索框常用

节流throttle:事件触发后,只执行一次函数,然后在固定的时间间隔内忽略后续的触发。即不管事件触发频率多高,都会按照固定的时间间隔来执行函数。滚动事件常用

防抖会在延迟时间结束后执行一次,而节流会在固定时间间隔内执行多次,但是限制了执行频率。
防抖适用于只需在最后一次触发时执行的场景,而节流适用于需要限制执行频率的场景。

20.数组去重的常用方法

  • ES6的Set集合去重:利用Set集合元素不重复的特性
  • indexOf去重 :建空数组,数组中无这个元素就push进去
  • 双层for循环,然后splice去重:循环比较,相同元素的删掉
  • sort()去重:排序,前后相同删一个
  • includes()去重:和indexOf相似
  • filter过滤去重
  • Map数据结构去重
  • hasOwnProperty()去重

21.bind的实现方式

在Web开发中,“bind”通常用于绑定事件处理程序到特定的元素。具体来说,使用JavaScript中的事件监听器可以实现绑定功能。

纯js实现:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Bind Example</title>
	</head>
	<body>

	<button id="myButton">Click me</button>

	<script>
	// 获取按钮元素
	var button = document.getElementById('myButton');
	
	// 创建事件处理程序
	function handleClick(event) {
	    console.log('Button clicked!');
	}
	
	// 绑定事件处理程序到按钮元素
	button.addEventListener('click', handleClick);
	</script>

	</body>
</html>

vue实现:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Bind Example</title>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
	</head>
	<body>
	
	<div id="app">
	    <button v-on:click="handleClick">Click me</button>
	</div>
	
	<script>
	new Vue({
	    el: '#app',
	    methods: {
	        handleClick: function() {
	            console.log('Button clicked!');
	        }
	    }
	});
	</script>
	
	</body>
</html>

22.事件循环

事件循环(Event Loop)是浏览器或Node.js等JavaScript运行环境中用来处理异步事件和回调函数的机制。
核心思想是不断地从任务队列中取出任务执行,直到队列为空。
下面这个博主讲的挺好的,可以看看⬇
深入理解事件循环,这一篇就够了!


四、Vue

1. MVVM架构,MVC架构

MVVM 是一种架构模式,用于设计和组织应用程序的代码结构,特别适用于用户界面层(如前端开发)的构建。
三个主要组成部分:

  • Model模型 :数据和业务逻辑
  • View视图:负责数据展示
  • ViewModel视图模型:视图和模型之间的中间人,负责处理视图的逻辑和数据绑定

MVC 是一种经典的架构模式,将应用程序划分为三个部分:模型(Model)、视图(View)和控制器(Controller)。
模型负责处理数据逻辑,视图负责用户界面呈现,控制器负责处理用户输入并更新模型和视图。

2.框架Vue和React的相同/不同?

不同:

  • 模版语法不同,react采用JSX语法,vue使用基于HTML的模版语法
  • 数据绑定不同,vue 使用双向数据绑定,react 则需要手动控制组件的状态和属性。
  • 状态管理不同,vue使用vuex状态管理,react使用redux状态管理
  • 组件通信不同,vue使用props和事件的方式进行父子组件通信,react则通过props和回调函数的方式进行通信。
  • 生命周期不同,vue有8个生命周期钩子,react有10个
  • 响应式原理不同,vue使用双向绑定来实现数据更新,react则通过单向数据流来实现

相同:

  • 组件化开发:VueReact都采用了组件化开发的方式,将用户界面划分为独立、可复用的组件,从而使代码更加模块化、可维护和可扩展。
  • 虚拟 DOM:Vue React 都使用虚拟 DOM 技术,通过在 JavaScript 和真实 DOM 之间建立一个轻量级的虚拟DOM层,实现高效的 DOM 更新和渲染。
  • 响应式更新:Vue React 都支持响应式更新,即当数据发生变化时,会自动更新相关的组件和视图,以保持用户界面的同步性。
  • 集成能力:Vue React 都具有良好的集成能力,可以与其他库和框架进行整合,例如 Vue 可以与 Vuex、Vue Router 等配套使用,React 可以与 Redux、React Router 等配套使用。

3. Vue2和Vue3的比较

  • Vue2使用的是optionsAPI ,Vue3使用composition API,更好的组织代码,提高代码可维护性
  • Vue3使用Proxy代理实现了新的响应式系统,比Vue2有着更好的性能和更准确的数据变化追踪能力。
  • Vue3引入了Teleprot组件,可以将DOM元素渲染到DOM树的其他位置,用于创建模态框、弹出框等。
  • Vue3全局API名称发生了变化,同时新增了watchEffect、Hooks等功能
  • Vue3对TypeScript的支持更加友好
  • Vue3核心库的依赖更少,减少打包体积
  • Vue3支持更好的Tree Shanking,可以更加精确的按需要引入模块

4.什么是SPA?和多页面的区别是什么?

simple page application 单页应用,前端应用程序的架构模式,只加载单个HTML 页面,并通过使用 JavaScript 动态地更新页面内容,局部刷新页面。

区别:

  • SPA,核心思想是在同一个页面中加载所有必要的HTML、CSS和JavaScript,并在用户与应用程序交互时动态地更新页面内容,而不需要重新加载整个页面;多页面,每个页面都有自己独立的HTML文档,用户在不同页面之间进行导航时会触发整个页面的重新加载。
  • SPA 使用JavaScript框架(如Vue.js、React、Angular等)来处理路由、视图渲染和数据请求,通过AJAX技术从服务器加载数据,然后通过DOM操作更新页面内容;多页面应用通常使用服务器端路由来处理不同页面的请求,每次用户导航到新页面时都会向服务器发送请求,服务器返回相应的HTML文档。
  • SPA 通常具有更流畅的用户体验,因为页面切换时无需重新加载整个页面;多页面应用在页面切换时会有明显的加载延迟。
  • SPA 在前端使用框架管理路由和视图,逻辑更加复杂,但可以提高开发效率和代码复用;多页面应用每个页面都是独立的,开发和维护成本相对较低。

多页面应用的优点是易于理解和维护,每个页面都是独立的,开发者可以根据需要独立开发和部署每个页面。

5.Vue对于性能优化都有哪些措施?

  • 使用生产环境构建版本
  • 使用异步组件:对于页面上不必要立即加载的组件,可以使用Vue.js的异步组件功能,将其按需加载,减少首次加载时的资源压力,提高页面加载速度
  • 合理使用v-ifv-showcomputed watch
  • 懒加载图片
  • 节流防抖

6.Vue的生命周期

在这里插入图片描述
创建前后:
beforeCreate(创建前): 数据观测和初始化事件还未开始,不能访问data、computed、watch、methods上的数据方法。
created(创建后):实例创建完成,可以访问data、computed、watch、methods上的数据方法,但此时渲染节点还未挂在到DOM上,所以不能访问。

挂载前后:
beforeMount(挂载前): Vue实例还未挂在到页面HTML上,此时可以发起服务器请求
mounted(挂载后):Vue实例已经挂在完毕,可以操作DOM

更新前后:
beforeUpdate(更新前): 数据更新之前调用,还未渲染页面
updated(更新后):DOM重新渲染,此时数据和界面都是新的。

销毁前后:
beforeDestorye(销毁前):实例销毁前调用,这时候能够获取到this
destoryed(销毁后):实例销毁后调用,实例完全被销毁。

7.Vue常用的指令和属性有哪些?

属性:data methods watch computed components
指令:v-if v-for v-show v-model v-bind v-html

8. Computed 和 Watch 的区别

watch:无缓存,可以监听单个数据或者数组,当数据发生变化时会执行对应的回调函数
computed:依赖现存数据生成新的数据。依赖数据发生变化时,computed会自动计算更新。computed属性值会被缓存

9.Vue组件间通信的方式?

  • Props / $emit(父子组件通信)
    父组件通过 props 向子组件传递数据,子组件通过$emit触发事件通知父组件。
  • $emit / $on(非父子组件之间通信)
    使用 Vue.js 的实例方法 $emit 在子组件中触发事件,然后使用 $on 在父组件中监听该事件。
  • Vuex(适用于大型应用或者组件之间状态交互较为复杂的情况)
  • $bus全局事件总线 ( 兄弟组件 )
  • ref属性(父子组件)
    可以创建一个空的 Vue 实例作为事件总线,用于在任何组件之间进行通信。

10.常见的事件修饰符及其作用

.stop 停止冒泡
.prevent 阻止默认事件,例如提交表单时阻止页面的重新加载。
.self 当事件是从自身触发时才触发
.once 只会触发一次
.native 监听组件根元素的原生事件,而不是组件内部的事件

11.v-if和v-show的区别?

v-if是动态地根据表达式的值来添加或移除DOM 元素。
v-show 是简单地根据表达式的值来控制元素的显示或隐藏,控制display: none显示隐藏

12.v-model 双向绑定的实现原理

  • 当作用在表单上:通过v-bind:value绑定数据,v-on:input来监听数据变化并修改value
  • 当作用在组件上:本质上是一个父子通信语法糖,通过props$emit实现。
    双向数据绑定的原理:
    采用数据劫持结合发布者-订阅者模式的方式,data数据在初始化的时候,会实例化一个Observe类,在它会将data数据进行递归遍历,并通过Object.defineProperty方法,给每个值添加上一个getter和一个setter。在数据读取的时候会触发getter进行依赖(Watcher)收集,当数据改变时,会触发setter,对刚刚收集的依赖进行触发,并且更新watcher通知视图进行渲染。

使用 Object.defineProperty() 来进行数据劫持的缺点:
该方法只能监听到数据的修改,监听不到数据的新增和删除,从而不能触发组件更新渲染。vue2中会对数组的新增删除方法push、pop、shift、unshift、splice、sort、reserve通过重写的形式,在拦截里面进行手动收集触发依赖更新。

13.什么叫语法糖?常见的语法糖有哪些?

“语法糖”(Syntactic Sugar)是一种编程语言的语法特性,它并不提供新的功能,但使得代码更易读、更易写。让开发人员更专注于业务逻辑的开发。
常用的语法糖:箭头函数、模板字符串、解构赋值

14.mixin 和 mixins 区别?

mixin 用于提供组件间可复用的选项,可以是一个函数或者对象
当一个组件使用 mixin 时,该组件会合并 mixin 对象中的选项到自身的选项中。这意味着,mixin中的数据、方法、生命周期钩子等会被合并到组件自身的对应选项中,从而实现了代码的复用。

// 定义一个 mixin 对象
var myMixin = {
  data: function () {
    return {
      count: 0
    }
  },
  methods: {
    increment: function () {
      this.count++
    }
  }
}
// 使用 mixin
var vm = new Vue({
  el: '#app',
  mixins: [myMixin]
})

mixins是一个数组,用于同时引入多个 mixin。这允许你在一个组件中混合多个 mixin,以实现更大程度的代码复用。

// 定义多个 mixin 对象
var myMixin1 = { /* ... */ }
var myMixin2 = { /* ... */ }
var myMixin3 = { /* ... */ }

// 在组件中同时使用多个 mixin
var vm = new Vue({
  el: '#app',
  mixins: [myMixin1, myMixin2, myMixin3]
})

15. data为什么是个函数不是个对象?route和router的区别?

data 是一个对象时,如果在多个组件实例中共享相同的对象,则这些组件实际上会共享相同的数据对象,这可能导致意外的行为,因为它们会相互影响。

而当 data 是一个函数时,每次创建一个新的组件实例时,Vue.js 都会调用该函数来生成一个新的数据对象,从而确保每个组件实例都拥有独立的数据副本。这种方式可以有效地避免数据共享和潜在的副作用。

$route是路由信息,$router是路由实例

16. 路由的hash和history模式的区别

  • hash模式
    开发中默认的模式,地址栏URL后携带#,后面为路由。
    原理是通过onhashchange()事件监听hash值变化,在页面hash值发生变化后,window就可以监听到事件改变,并按照规则加载相应的代码。hash值变化对应的URL都会被记录下来,这样就能实现浏览器历史页面前进后退。
  • history模式
    history模式中URL没有#,这样相对hash模式更好看,但是需要后台配置支持。
    history原理是使用HTML5 history提供的pushState、replaceState两个API,用于浏览器记录历史浏览栈,并且在修改URL时不会触发页面刷新和后台数据请求。

17.Vue中如何设置动态路由?

举个栗子来说明

  • 定义动态路由:在 Vue Router 中定义路由时,可以使用动态片段来表示动态部分,通常以冒号 : 开头
const router = new VueRouter({
  routes: [
     //  /user/:id 中的 :id 就是动态的部分,它表示用户的ID。
    { path: '/user/:id', component: User }
  ]
})
  • 在组件中使用动态路由参数:在组件中,你可以使用 $route.params 来访问动态路由的参数。
const User = {
  template: '<div>User ID: {{ $route.params.id }}</div>'
}
  • 触发动态路由:你可以通过在应用中导航到包含动态路由的路径来触发动态路由的加载。
// 在应用中导航到动态路由路径
router.push('/user/123')

传参:
params传参
路由配置:/index/:id
路由跳转:this.$router.push({name:'index',params: {id:"zs"}});
路由参数获取:$route.params.id
最后形成的路由:/index/zs
query传参
路由配置:/index 正常的路由配置
路由跳转:this.$rouetr.push({path:'index',query:{id:"zs"}});
路由参数获取: $route.query.id
最后形成的路由: /index?id=zs

两种传参区别:
获取参数方式不一样,一个通过$route.params,一个通过 $route.query
参数的生命周期不一样,query参数在URL地址栏中显示不容易丢失,params参数不会在地址栏显示,刷新后会消失

18. Vue中key的作用

作用主要是为了高效的更新虚拟DOM
原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,减少DOM操作量,提高性能。

19.index可以用作key吗?为什么?

不建议,当列表发生变化时可能会影响key的改变,从而重新渲染页面,可能会造成性能问题。

20.【原理】Vue是如何收集依赖的?

依赖收集发生在defineReactive()方法中

  • 在方法内new Dep()实例化一个Dep()实例,
  • 然后在getter中通过dep.depend()方法对数据依赖进行收集,
  • 然后在settter中通过dep.notify()通知更新。

整个Dep其实就是一个观察者,把收集的依赖存储起来,在需要的时候进行调用。在收集数据依赖的时候,会为数据创建一个Watcher,当数据发生改变通知每个Watcher,由Wathcer进行更新渲染。

21. 【原理】slot是什么?作用和原理是什么?

slot(插槽),一般在封装组件的时候使用,在组件内不知道以那种形式来展示内容时,可以用slot来占据位置
分三类: 默认插槽,具名插槽和作用域插槽

实现原理:当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm.$slot中,默认插槽为vm.$slot.default,具名插槽为vm.$slot.xxxxxx 为插槽名,当组件执行渲染函数时候,遇到slot标签,使用$slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可称该插槽为作用域插槽。

22.【原理】$nextTick 原理及作用

nextTick() 是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数。

原理: 利用 JavaScript 的事件循环机制,将回调函数推入事件队列,在 DOM更新完成后执行这些回调函数。

因为在created()钩子函数中,页面的DOM还未渲染,这时候也没办法操作DOM,所以,此时如果想要操作DOM,必须将操作的代码放在nextTick()的回调函数中。

23.【原理】Vue模版编译原理

基本原理是将 Vue 模板字符串转换为渲染函数,这个渲染函数会生成 Virtual DOM,并最终渲染成真实的 DOM。

Vue 模板编译的基本流程:

  • 模板解析:首先,Vue 会将模板字符串解析成 AST(抽象语法树),AST 是一个树形结构,用来表示模板的语法结构和各个节点之间的关系。
  • AST 优化:在得到 AST 后,Vue 会对其进行一些优化操作,比如静态节点提升、静态属性提升等。这些优化操作可以减少渲染时的开销,提高渲染性能。
  • 生成渲染函数:接下来,Vue 会根据优化后的 AST 生成渲染函数。渲染函数的作用是根据数据生成 Virtual DOM
  • 渲染 Virtual DOM(虚拟DOM):当数据发生变化时,Vue 会重新执行渲染函数,生成新的 Virtual DOM。然后,Vue 会将新的 Virtual DOM 与之前的 Virtual DOM 进行对比,找出差异。
  • 更新真实 DOM:最后,Vue 将差异应用到真实的 DOM上,完成页面的更新。

24.【原理】Vuex的原理

在这里插入图片描述

  • Vue Components负责接收用户操作交互行为,执行dispatch触发对应的action进行回应
  • dispatch唯一能执行action的方法
  • action用来接收components的交互行为,包含异步同步操作
  • commitmutation进行提交,唯一能执行mutation的方法
  • mutation唯一可以修改state状态的方法
  • state页面状态管理容器,用于存储状态
  • getters读取state方法

Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新。

25.Vuex中action和mutation的区别?

  • mutation更专注于修改state,必须是同步执行。
  • action提交的是mutation,而不是直接更新数据,可异步。
  • action可以包含多个mutation

26.虚拟DOM的理解

结构:虚拟 DOM 是一个与真实 DOM 对应的 JavaScript 对象树。它是由节点对象组成的树状结构,每个节点对象表示了真实 DOM 中的一个元素,包括元素的标签名、属性、子节点等信息。
更新:当数据更新时,生成新的虚拟DOM,和旧的虚拟DOM比较,根据差异生成DOM操作指令应用到真实DOM上,完成页面的更新。
优势:可以减少频繁的 DOM 操作,从而提高页面的渲染性能。同时,虚拟 DOM 也提供了一种更加抽象的方式来操作 DOM,使得开发者可以更方便地管理页面的状态和结构。

27.【原理】DIFF算法原理

虚拟DOM的比对算法。当数据发生变化的时候,diff会对新旧虚拟DOM进行对比,只渲染有变化的部分。

对比是不是同类型标签,不是同类型直接替换
如果是同类型标签,执行patchVnode方法,判断新旧vnode是否相等。如果相等,直接返回。
新旧vnode不相等,需要比对新旧节点,比对原则是以新节点为主,主要分为以下几种。

newVnodeoldVnode都有文本节点,用新节点替换旧节点。
newVnode有子节点,oldVnode没有,新增newVnode的子节点。
newVnode没有子节点,oldVnode有子节点,删除oldVnode中的子节点。
newVnodeoldVnode都有子节点,通过updateChildren对比子节点。


五、ES6

1.let var const的区别

varletconst
作用域函数作用域块级作用域块级作用域
多次声明变量允许,后者覆盖前者不允许不允许
声明类型声明变量声明变量声明常量,一旦赋值不能修改
初始化可不赋值可不赋值必须赋值

const : 对于基本类型的值(如数字、字符串、布尔值),值不能被修改;对于引用类型的值(如对象、数组),可以修改其属性或元素,但不能重新赋值为另一个对象或数组。

优先使用 const,除非需要重新赋值的情况才使用 let。
尽量避免使用 va,容易导致变量污染和意外的行为。

浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。

2. 箭头函数和普通函数的区别?

箭头函数普通函数
基本结构 const arrowFunction = () => { // 函数体 };function regularFunction(){ // 函数体 }
this指向没有自己的this普通函数的 this 是在运行时确定的,它的值取决于函数的调用方式。
arguments没有自己的 arguments 对象,但可以访问外围函数的arguments 对象有自己的 arguments对象,可以访问函数调用时传入的参数
new 关键字不能作为构造函数可以作为构造函数创建实例

箭头函数适用于简单的函数表达式,具有更简洁的语法和固定的 this 指向。
普通函数适用于更复杂的函数逻辑,并且可以作为构造函数来创建实例对象,具有动态的 this 指向和 arguments 对象。

3.箭头函数this的指向?

箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象。
常见的this指向:

  • 全局作用域中或者普通函数中this指向全局对象window
  • 立即执行函数this必定指向window
  • 定时器this指向window
  • 事件this指向事件源对象
  • 方法中谁调用就指向谁
  • 构造函数this指向对象实例

4. Set、Map的区别

SetMapES6 中新增的两种数据结构,它们都用于存储数据

SetMap
创建let s = new Set([1,2,3,4,5])let m = new Map([ ['key1', 'value1'],['key2', 'value2'] ]);
数据结构集合,不允许重复键值对集合,键唯一,值可重复
存储的值值的集合,其中每个值只能出现一次键值对,其中每个键对应一个值
访问没有索引,不能通过索引访问通过键来访问和操作Map中的元素
操作add() 方法添加新元素, delete() 方法删除元素, has() 方法检查元素是否存在。set() 方法添加新的键值对, delete() 方法删除键值对,get() 方法获取键对应的值,has()方法检查键是否存在
遍历使用 forEach 方法或者for...of循环遍历 Set 中的元素使用forEach方法或者 for...of 循环遍历Map 中的键值对
应用场景存储唯一的值且无序存储键值对,根据键快速查找对应值,有序

如果你只需要存储一组唯一的值,并且不关心顺序,可以使用 Set。
如果你需要存储键值对,并且需要根据键来快速查找对应的值,可以使用 Map。
如果需要保持插入顺序,并且需要键值对,也可以考虑使用 Map。
Set是类似数组的一种的数据结构,类似数组的一种集合,但在Set中没有重复的值

5.Map和Object的区别

  • 键的类型Map 的键可以是任意数据类型(包括对象、函数、NaN 等),而 Object 的键只能是字符串或者 Symbol 类型。
  • 键值对的顺序Map中的键值对是按照插入的顺序存储的,而对象中的键值对则没有顺序。
  • 键值对的遍例Map 的键值对可以使用for...of进行遍历,而Object的键值对需要手动遍历键值对。
  • 继承关系Map 没有继承关系,而Object是所有对象的基类。

6.map和weakMap的区别

它们是 JavaScript 中的两种不同的键值对集合,主要区别如下:

  • 键的类型map的键可以是任意类型,weakMap键只能是对象类型。
  • 回收map 使用常规的引用来管理键和值之间的关系,因此即使键不再使用,map 仍然会保留该键的内存。weakMap 使用弱引用来管理键和值之间的关系,因此如果键不再有其他引用,垃圾回收机制可以自动回收键值对。

7.说说你对Promise的理解?

  • 异步操作管理Promise 用于管理异步操作,例如 AJAX 请求、文件读取、定时器等。
  • Promise的状态pending(进行中)、fulfilled(已成功)和rejected(已失败)。初始状态是 pending,当异步操作成功完成时,Promise 变为 fulfilled 状态,当异步操作失败时,Promise 变为rejected状态。
  • 链式调用Promise 支持链式调用,这意味着你可以在一个 Promise 的成功或失败后继续执行其他操作,避免回调地狱
  • then() 方法: 通过 then() 方法来注册成功和失败的回调函数。then() 方法接受两个参数:成功回调函数和失败回调函数,分别在异步操作成功和失败时被调用。
  • catch() 方法 Promise 通过 catch() 方法来捕获失败的情况。catch() 方法用于注册当 Promise 进入 rejected 状态时的回调函数。
  • Promise.all() 方法Promise.all() 方法接受一个由 Promise 对象组成的数组作为参数,返回一个新的 Promise对象。当所有 Promise 对象都变为 fulfilled 状态时,新 Promise 对象变为fulfilled状态;当任意一个 Promise 对象变为 rejected 状态时,新 Promise 对象变为 rejected 状态。
  • Promise.race() 方法Promise.race() 方法同样接受一个由Promise对象组成的数组作为参数,返回一个新的Promise对象。当数组中的任意一个Promise对象变为 fulfilledrejected 状态时,新 Promise 对象的状态就会跟着变化。

缺点:
无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

8.对async/await 的理解

一种语法糖
async/await 是 ES8中引入的一种异步编程解决方案,它建立在 Promise 的基础上,提供了更加简洁和直观的方式来处理异步操作。

它能实现的效果都能用then链来实现,它是为优化then链而开发出来的。
通过async关键字声明一个异步函数, await 用于等待一个异步方法执行完成,并且会阻塞执行。
async 函数返回的是一个 Promise 对象,如果在函数中 return 一个变量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。如果没有返回值,返回 Promise.resolve(undefined)

  • 异步函数声明: 使用 async 关键字声明的函数称为异步函数。异步函数内部可以使用 await 关键字来暂停执行,并等待 Promise 对象的解决(即状态变为 fulfilled)。
  • await 表达式 await关键字只能在异步函数中使用。它暂停当前异步函数的执行,等待 Promise 对象的解决。
  • 错误处理: 异步函数内部可以使用 try...catch 结构来捕获 Promise 对象的拒绝(即状态变为 rejected)以及任何被抛出的错误

9. 对于ES6的理解?( 添加了哪些内容)

letconst 声明,箭头函数,模板字符串,解构赋值,默认参数值,类和继承,Promise 对象,模块化,迭代器和生成器,MapSet 数据结构,ES6 允许在对象中使用 super 方法,

10.ES6模块和CommonJS模块有什么区别?

ES6模块CommonJS模块
语法import 和 export 导入和导出require() 函数,module.exports 或 exports 对象来导出
加载时机静态加载, import 都会在代码执行之前被处理动态加载,模块在需要时才会被加载和执行
导入方式默认导出和命名导出,可以同时导出多个变量或函数单一导出,通过 module.exports 导出一个对象或者使用 exports 导出一个对象的属性
作用域有自己的作用域没有自己的作用域,模块中定义的变量和函数可在其他的模块中访问

11. 原型和原型链

原型(Prototype): 每个 JavaScript 对象(除了 null)都有一个原型,它是对象的一个属性,可以是另一个对象或者 null。对象通过原型继承属性和方法。
构造函数(Constructor): 构造函数是用来创建对象的函数,它们通常以大写字母开头,用于实例化新对象。在 JavaScript 中,构造函数也是对象,它们具有一个 prototype 属性,该属性指向构造函数的原型对象。
继承(Inheritance): 在 JavaScript 中,继承是通过原型链来实现的。子对象可以从父对象继承属性和方法,这样可以减少代码重复并实现代码的复用。
在这里插入图片描述

12.对于闭包的理解和它的使用场景

理解:函数内部定义的函数可以访问函数外部的变量,即使外部函数已经执行结束,内部函数仍然可以访问外部函数的变量。
闭包形成了一个作用域链,内部函数可以访问外部函数的变量,而外部函数无法访问内部函数的变量。

function outerFunction() {
    var outerVariable = "I am from outer function";
    // 内部函数形成闭包,可以访问外部函数的变量
    function innerFunction() {
        console.log(outerVariable); // 内部函数可以访问外部函数的变量
    }
    return innerFunction; // 返回内部函数
}

// 调用外部函数,返回内部函数
var closure = outerFunction();

// 调用内部函数,依然可以访问外部函数的变量
closure(); // 输出:"I am from outer function"

使用场景

  • 私有化变量和方法
  • 模块化开发: 闭包可以用于实现模块化开发,将相关的变量和方法封装在闭包内部,只暴露出需要对外使用的接口
  • 异步编程: 在异步编程中,闭包可以用来捕获异步操作中的状态,保留异步操作所需的上下文信息,例如回调函数中的变量
  • 函数柯里化: 闭包可以用于函数柯里化(Currying),即将接受多个参数的函数转换为接受单个参数的函数,并返回一个新的函数处理剩余参数。
  • 事件处理程序: 闭包可以用于保存事件处理程序中的状态信息,例如保存计数器的状态或者保存当前选中的 DOM 元素等。

缺点:创建的变量不能被回收,容易消耗内存,使用不当会导致内存溢出,解决办法就是不需要使用的时候将变量设为null;
闭包并不一定会造成内存泄漏,如果在使用闭包后变量没有及时销毁,可能会造成内存泄漏的风险。

13.对作用域、作用域链的理解

作用域是一个变量或函数的可访问范围,作用域控制着变量或函数的可见性和生命周期。

  • 全局作用域:全局访问
  • 函数作用域:只能在函数中访问
  • 块级作用域(ES6):在代码块中访问

作用域链:变量在指定的作用域中没有找到,会依次向上寻找,直到找到全局作用域,这样的查找过程。

14. call() 、bind()、 apply() 的用法和区别?

call(), bind(), 和 apply() 的作用是改变函数执行时的上下文(即 this 关键字所指向的对象)。
参数不同:

//thisArg : 在 call() 方法中指定的 this 值。可以是任何 JavaScript 对象
function.call(thisArg, arg1, arg2, ...)   //一个或多个参数列表
function.apply(thisArg, [argsArray])  //一个参数数组
function.bind(thisArg[, arg1[, arg2[, ...]]])

call和apply的区别在于传参,call、bind都是传入对象。apply传入一个数组。
call、apply改变this指向后会立即执行函数,bind在改变this后返回一个函数,不会立即执行函数,需要手动调用。

15.哪些情况会导致内存泄漏?

  • 意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。
  • 被遗忘的计时器或回调函数:设置了setInterval定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。
  • 脱离 DOM 的引用:获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。
  • 闭包:不合理的使用闭包,从而导致某些变量一直被留在内存当中。

16.浏览器的垃圾回收机制(GC)

  • 标记清除(Mark and Sweep):最常用。当变量进入执行环境(例如函数中声明一个变量)时,它会被标记为“进入环境”。当变量离开环境时(例如函数执行结束),它会被标记为“离开环境”。引用计数为零的变量会被清除。
  • 引用计数(Reference Countin):常见。当变量被引用时,其引用计数加一;当变量不再被引用时,其引用计数减一。当引用计数为零时,变量被视为不再需要,可以被回收。
  • 分代回收(Generational Collection):将内存分为不同的代,通常是新生代和老生代。
    大部分对象在创建后很快变得不再使用,因此它们被分配到新生代。
    垃圾回收机制更频繁地检查新生代,以便及时回收不再使用的对象。
  • 增量式垃圾回收(Incremental Garbage Collection):
    将垃圾回收过程分解为多个阶段,每个阶段执行一小部分垃圾回收工作,然后让 JavaScript应用程序继续执行。
  • 空闲时间回收(Idle-time Garbage Collection):当浏览器处于空闲状态时(例如用户没有进行交互),垃圾回收机制会优先执行。
  • 手动触发垃圾回收:有时,JavaScript 引擎提供了手动触发垃圾回收的方法,例如 window.gc(),但这并不是标准的 JavaScript API,也不建议经常使用,因为它可能会干扰垃圾回收机制的自动优化。

小结:仅供学习参考,欢迎指正

会继续更新…
祝大家面试都能过过过!!!
offer拿到手软 ^皿^
在这里插入图片描述

  • 35
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值