• 2023前端面试题


    一.HTML篇

    1.HTML是什么?它的缩写代表什么?

    HTML代表"超文本标记语言"(Hypertext Markup Language),它是一种用于创建网页结构和内容的标记语言。

    2.HTML文档的基本结构是什么?

    基本的HTML结构包括声明、元素、元素(包含元数据),以及元素(包含页面内容)。

    3.HTML5新特性?

    语义化元素: HTML5引入了一些新的语义化元素,如

    4.HTML元素和HTML标签有什么区别? 

    HTML元素是由开始标签、内容和结束标签组成的,而HTML标签只是开始标签或结束标签的一部分。

    5.前端页面有那三层构成?

    1. 结构层(Structure Layer)

      结构层是网页的基本骨架,它定义了网页的整体布局和内容组织。在HTML中,结构层由HTML标记和元素组成,包括标题、段落、列表、表格等。这些元素构成了网页的基本结构,用于定义文本内容、图像、链接等。
    2. 样式层(Presentation Layer)

      样式层负责定义网页的外观和布局,使其看起来更吸引人并符合设计要求。在前端开发中,通常使用CSS(层叠样式表)来控制样式层。CSS可以用来设置字体、颜色、边距、内边距、背景、定位等网页元素的外观和排列方式。
    3. 行为层(Behavior Layer)

      行为层是网页的交互部分,它包括用户与网页进行互动的功能和动态行为。通常使用JavaScript来实现行为层,JavaScript可以用于添加交互效果、响应用户输入、验证表单、异步加载数据等。行为层使网页更具动态性和交互性。

    6.HTML中的元数据是什么?它们放在哪里? 

    元数据包括页面的标题、字符集设置、关键词等信息。它们通常放在元素中,如</code>和<code><meta></code>标签。</p> </blockquote> <p> 7.<strong>如何在HTML中创建超链接?</strong></p> <blockquote> <p>使用<code><a></code>元素来创建超链接,设置<code>href</code>属性来指定链接目标。</p> </blockquote> <p><strong> 8.src和href的区别?</strong></p> <blockquote> <ul><li><code>src</code> 通常用于加载外部媒体资源或嵌入式内容,并且在加载时会影响页面的布局和呈现。</li><li><code>href</code> 通常用于创建超链接或关联外部资源,点击链接会导航到新的页面或资源,而不会对当前页面进行布局更改。</li></ul> </blockquote> <p><strong>9.HTML标签在标准流的表现是什么样?</strong></p> <blockquote> <p>HTML标签的表现方式在标准流(也称为文档流)中取决于它们的类型(块级元素、内联元素、替换元素等)。标准流是浏览器用于排列和渲染HTML元素的一种基本方式,它考虑元素的类型、位置和文档结构。以下是不同类型HTML标签在标准流中的一般表现:</p> <p></p> <p><strong>块级元素(Block-level Elements):</strong></p> <ul><li>块级元素会独占一行或多行,它们从上到下依次排列。</li><li>块级元素会在页面中自动换行,每个块级元素都会另起一行。</li><li>常见的块级元素包括<code><div></code>、<code><p></code>、<code><h1></code>到<code><h6></code>、<code><ul></code>、<code><ol></code>、<code><li></code>、<code><table></code>等。</li></ul> <p><strong>内联元素(Inline Elements):</strong></p> <ul><li>内联元素不会强制换行,它们会在同一行上水平排列。</li><li>内联元素只占据它们包含的内容的宽度,不会独占一行。</li><li>常见的内联元素包括<code><span></code>、<code><a></code>、<code><strong></code>、<code><em></code>、<code><img></code>、<code><br></code>等。</li></ul> <p><strong>替换元素(Replaced Elements):</strong></p> <ul><li>替换元素是一种特殊类型的内联元素,但它们的内容通常由外部资源来替代,如图像、音频、视频等。</li><li>替换元素会在页面中占据一定的空间,根据外部资源的尺寸和属性来确定大小。</li><li>常见的替换元素包括<code><img></code>、<code><audio></code>、<code><video></code>。</li></ul> </blockquote> <p> 10.<strong>HTML中的表格如何创建?</strong></p> <blockquote> <p>表格可以使用<code><table></code>、<code><tr></code>、<code><td></code>等标签创建,其中<code><table></code>用于定义表格,<code><tr></code>用于定义行,<code><td></code>用于定义单元格。</p> </blockquote> <p> 11.<strong>HTML中的表单是什么?</strong></p> <blockquote> <p>表单是用于收集用户输入数据的元素,可以使用<code><form></code>标签创建,包括文本框、单选按钮、复选框等表单控件。</p> </blockquote> <p>12.<strong>什么是HTML属性?</strong></p> <blockquote> <p> HTML属性是提供有关HTML元素的附加信息的键值对,如<code><a href="https://www.example.com"></code>中的<code>href</code>属性。</p> </blockquote> <p><strong>13.严格模式和混杂模式?</strong></p> <blockquote> <p><strong>混杂模式(Quirks Mode)</strong>:</p> <ul><li>混杂模式是一种兼容性模式,当浏览器检测到网页没有按照现代标准编写时,会进入混杂模式。这通常发生在早期的HTML文档中,或者在没有正确声明文档类型的情况下。</li></ul> <p><strong>严格模式(Strict Mode)</strong>:</p> <ul><li>严格模式是一种更加规范和标准化的模式,它要求网页按照HTML和CSS的标准规范编写。在HTML中,可以通过在文档开头添加正确的文档类型声明(<!DOCTYPE>)来启用严格模式。</li></ul> </blockquote> <p><strong>14.iframe是什么?</strong></p> <blockquote> <p><code><iframe></code> 是 HTML 中的一个标签,用于嵌套另一个HTML文档或外部资源(如另一个网页)到当前页面中。这个标签允许您在一个网页中嵌套另一个独立的网页,从而创建内联框架(Inline Frame)或嵌套的窗口。</p> <p>使用 <code><iframe></code> 可以实现各种功能,包括但不限于以下几种:</p> <ol><li> <p><strong>嵌套其他网页</strong>:您可以在您的网页中嵌套其他网站的内容,如地图、社交媒体小部件、视频等。</p> </li><li> <p><strong>显示嵌入式内容</strong>:可以嵌套媒体,如YouTube视频、Google地图、Twitter帖子等。</p> </li><li> <p><strong>创建内联框架</strong>:可以将一部分内容包装在内联框架中,使其在页面中独立显示。</p> </li><li> <p><strong>加载外部应用程序</strong>:可以将外部应用程序嵌套到您的网页中,例如在线文档编辑器、在线游戏等。</p> </li></ol> <p>需要注意的是,虽然 <code><iframe></code> 可以实现各种有用的功能,但要谨慎使用,因为滥用 <code><iframe></code> 可能会导致安全问题,如点击劫持(clickjacking)等。确保只嵌套信任的内容,并了解如何正确配置 <code>sandbox</code> 属性以增加安全性。</p> </blockquote> <p><strong>15.script 标签中 defer 和 async 的区别? </strong></p> <blockquote> <p style="margin-left:0;"><span style="color:#0d0016;">在HTML的<code><script></code>标签中,<code>defer</code>和<code>async</code>用于控制脚本的加载和执行方式的属性,它们之间有一些重要的区别:</span></p> <ol style="margin-left:0;"><li> <p style="margin-left:0;"><strong>加载方式</strong>:</p> <ul><li><code>async</code>:异步加载脚本,阻止页面的解析和渲染,一旦下载完成,立即执行。多个标记属性的脚本是需要加载和执行的,执行顺序不确定,取决于<code>async</code>哪个脚本先下载完成。</li><li><code>defer</code>:脚本也是异步加载的,但是它会保持脚本的执行顺序与它们在页面中的顺序一致。脚本会在文档完成解析之后,DOMContentLoaded 事件触发之前按照顺序执行。</li></ul></li><li> <p style="margin-left:0;"><strong>执行时机</strong>:</p> <ul><li><code>async</code>:脚本一旦下载完成,就会立即执行,无论其在文档中的位置如何。</li><li><code>defer</code>:脚本会在文档解析完成之后,DOMContentLoaded 事件触发之前执行,保证脚本在文档中的顺序执行。</li></ul></li><li> <p style="margin-left:0;"><strong>适用场景</strong>:</p> <ul><li><code>async</code>:适用于不依赖于页面解析过程中的其他脚本或文档元素的脚本,通常用于第三方或独立的脚本。</li><li><code>defer</code>:适用于等待页面解析完成后执行的脚本,可以确保脚本访问和操作页面中的元素。</li></ul></li></ol> <pre data-index="0" class="set-code-show" name="code"><code class="language-html hljs language-xml"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-meta"><!DOCTYPE <span class="hljs-keyword">html</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"><<span class="hljs-name">html</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"><<span class="hljs-name">head</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">title</span>></span>Script Loading<span class="hljs-tag"></<span class="hljs-name">title</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"script1.js"</span> <span class="hljs-attr">async</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"script2.js"</span> <span class="hljs-attr">defer</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"></<span class="hljs-name">head</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"><<span class="hljs-name">body</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag"><<span class="hljs-name">p</span>></span>Hello, world!<span class="hljs-tag"></<span class="hljs-name">p</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"></<span class="hljs-name">body</span>></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-tag"></<span class="hljs-name">html</span>></span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>在上面的示例中,<code>script1.js</code>使用<code>async</code>属性,它会异步加载并立即执行,而<code>script2.js</code>使用<code>defer</code>属性,会等待文档解析完成后执行,保证执行顺序正确。 </p> </blockquote> <h2><a name="t1"></a>二.CSS篇</h2> <p><strong>1.什么是CSS?它的作用是什么?</strong></p> <blockquote> <p>CSS是层叠样式表(Cascading Style Sheets)的缩写,它是一种用于控制网页或文档的外观和布局的样式语言。CSS的主要作用是将样式与内容分离开来,这样可以更容易地对网页的外观进行管理和调整。以下是CSS的主要作用</p> <ol><li> <p>样式化网页元素:CSS允许开发者定义网页上各个元素的样式,如文字颜色、字体、背景颜色、边框、间距等。通过为元素应用不同的样式规则,可以使页面看起来更漂亮、更有吸引力。</p> </li><li> <p>布局控制:CSS可以用来定义网页元素的位置和大小,从而控制页面的布局。开发者可以使用CSS的布局属性来实现各种不同的页面布局,包括响应式设计、网格布局、居中对齐等。</p> </li><li> <p>网页响应性:CSS可以帮助开发者创建响应式设计,使网页能够适应不同屏幕尺寸和设备,从而提供更好的用户体验。通过媒体查询和适应性样式,可以根据用户的设备动态调整页面布局和样式。</p> </li><li> <p>维护性和可重用性:通过将样式信息集中存储在CSS文件中,可以轻松地在整个网站或应用程序中重复使用样式规则。这提高了代码的可维护性,因为一次更新样式规则就可以应用到所有相关的元素上。</p> </li><li> <p>提高性能:使用CSS来定义页面样式可以减少页面加载时间,因为浏览器可以缓存样式信息并在多个页面之间共享。这有助于提高网页的性能和加载速度。</p> </li></ol> </blockquote> <p><strong>2.请解释CSS盒模型是什么,它由哪些部分组成?</strong></p> <blockquote> <p>CSS盒模型是一种用来描述HTML元素在页面布局中所占空间的模型。它定义了一个元素的可视区域,并将其分为不同的部分,以便确定元素的大小、内边距、边框和外边距。CSS盒模型由以下几个主要部分组成:</p> <ol><li> <p>内容区域(Content Area):内容区域是元素包含的实际内容,例如文本、图像或其他媒体。这个区域的大小由元素的<code>width</code>(宽度)和<code>height</code>(高度)属性定义。</p> </li><li> <p>内边距(Padding):内边距是内容区域与元素边框之间的空白区域。它可以通过<code>padding</code>属性来定义,用于控制元素内容与边框之间的间距。</p> </li><li> <p>边框(Border):边框是围绕内容区域和内边距的线条或边界。边框的样式、宽度和颜色可以通过<code>border</code>属性来设置。</p> </li><li> <p>外边距(Margin):外边距是元素边框与相邻元素之间的空白区域。外边距可以通过<code>margin</code>属性来定义,用于控制元素与其周围元素之间的间距。</p> </li></ol> <p>在CSS盒模型中,这些部分是相互嵌套的,从内到外依次是内容区域、内边距、边框和外边距。这些部分的总和决定了元素在页面上所占的空间。</p> <p>需要注意的是,CSS盒模型有两种不同的表示方式:标准盒模型(content-box)和IE盒模型(border-box)。在标准盒模型中,元素的宽度和高度仅包括内容区域,而在IE盒模型中,元素的宽度和高度包括了内容区域、内边距和边框。开发者可以通过设置CSS属性<code>box-sizing</code>来选择使用哪种盒模型表示方式。</p> </blockquote> <p><strong>3.什么是浮动(float)?它的作用是什么?如何清除浮动?</strong></p> <blockquote> <p>浮动(float)是CSS中的一种布局属性,用于控制元素在其容器中的水平位置。浮动的主要作用是使元素能够在文本流中沿着其容器的左侧或右侧浮动,并允许其他元素围绕它。主要用途包括实现多列布局、文字环绕图像以及创建网页导航菜单等。</p> <p>浮动的主要属性是<code>float</code>,其可能的值包括:</p> <ul><li> <p><code>float: left;</code>:元素将向左浮动,其他元素将尝试围绕其右侧。通常用于创建多列布局或文字环绕图像。</p> </li><li> <p><code>float: right;</code>:元素将向右浮动,其他元素将尝试围绕其左侧。也可用于创建多列布局或文字环绕图像。</p> </li></ul> <p>浮动元素会被移出文档流,这意味着其他元素会忽略它,不再占用其位置。这也是清除浮动的原因,因为浮动元素可能导致容器坍塌(container collapse),从而影响布局。清除浮动是确保容器能够正确包含浮动元素的一种技术。</p> <p>常见的清除浮动方法</p> <pre data-index="1" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-class">.clearfix</span><span class="hljs-selector-pseudo">::after</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">display</span>: table;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">clear</span>: both;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>在包含浮动元素的容器上添加一个带有<code>clearfix</code>类的样式,它会在容器的末尾插入一个清除浮动的伪元素。</p> <pre data-index="2" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-class">.container</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">overflow</span>: auto; <span class="hljs-comment">/* 或 overflow: hidden; */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>在包含浮动元素的容器上设置<code>overflow</code>属性为<code>auto</code>或<code>hidden</code>,这将创建一个新的块级格式化上下文(BFC),从而包含浮动元素。</p> <p>使用<code>clear</code>属性: 在浮动元素后面添加一个带有<code>clear</code>属性的空元素,如</p> <pre data-index="3" class="set-code-show" name="code"><code class="language-css hljs"><<span class="hljs-selector-tag">div</span> style="<span class="hljs-attribute">clear</span>: both;"></<span class="hljs-selector-tag">div</span>></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>这会在浮动元素的下方创建一个新的块级元素,从而清除浮动。</p> </blockquote> <p><strong>4.什么是CSS伪类?举例说明伪类的用法。 </strong></p> <blockquote> <p>CSS伪类是一种用于选择文档中特定状态或特定元素的选择器。它们允许你为元素的特定状态或位置应用样式,而不是基于元素的类名或标签名进行选择。伪类以冒号(:)开头,后面跟着伪类的名称。</p> <p><code>1.:hover</code> 伪类:当用户鼠标悬停在元素上时应用样式。</p> <pre data-index="4" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">color</span>: red;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>2. <code>:active</code> 伪类:当元素被激活(例如,被点击)时应用样式。</p> <pre data-index="5" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:active</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">background-color</span>: yellow;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><code>3.:focus</code> 伪类:当元素获得焦点时应用样式(通常用于表单元素)。</p> <pre data-index="6" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:focus</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">border-color</span>: blue;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><code>4.:nth-child</code> 伪类:根据元素在其父元素中的位置选择元素。</p> <pre data-index="7" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">li</span><span class="hljs-selector-pseudo">:nth-child</span>(even) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">background-color</span>: lightgray;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><code>5.:not</code> 伪类:选择不匹配指定选择器的元素。</p> <pre data-index="8" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">:not</span>(<span class="hljs-selector-class">.special</span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">font-weight</span>: bold;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><code>6.:first-child</code> 和 <code>:last-child</code> 伪类:分别选择父元素的第一个和最后一个子元素。</p> <pre data-index="9" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">li</span><span class="hljs-selector-pseudo">:first</span>-child {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">font-weight</span>: bold;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">li</span><span class="hljs-selector-pseudo">:last-child</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">color</span>: red;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p></p> </blockquote> <p><strong>5.什么是伪元素 ?</strong></p> <blockquote> <p>伪元素(Pseudo-elements)是CSS中的一种选择器,用于选择元素的特定部分或生成的内容,而不是选择整个元素。伪元素以两个冒号(::)开头,后面跟着伪元素的名称。伪元素允许开发者在文档中的元素内部或外部插入额外的样式和内容,以实现更丰富的页面布局和样式效果。</p> <p><code>1.::before</code> 伪元素:用于在元素的内容前面插入额外的内容。</p> <pre data-index="10" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::before</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">content</span>: <span class="hljs-string">"前置内容: "</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>2.<code>::after</code> 伪元素:用于在元素的内容后面插入额外的内容。</p> <pre data-index="11" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">::after</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">content</span>: <span class="hljs-string">" (链接)"</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>3.<code>::first-line</code> 伪元素:选择元素的第一行文本。</p> <pre data-index="12" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::first-line</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">font-weight</span>: bold;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>4.<code>::first-letter</code> 伪元素:选择元素的第一个字母。</p> <pre data-index="13" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::first-letter</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">font-size</span>: <span class="hljs-number">150%</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>5.<code>::selection</code> 伪元素:用于选择文本时的样式。</p> <pre data-index="14" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-pseudo">::selection</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">background-color</span>: yellow;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">color</span>: black;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>上述示例将选择文本的背景颜色设为黄色,文本颜色设为黑色。</p> </blockquote> <p><strong>6.什么是BEM(块、元素、修饰符)命名规范?它的作用是什么? </strong></p> <blockquote> <p> BEM是一种CSS命名规范,全称为块(Block)、元素(Element)、修饰符(Modifier)。它旨在帮助开发者更清晰地组织和命名CSS类,以实现可维护、可扩展和易理解的代码。BEM的核心思想是将页面分解成块、元素和修饰符三个层次,以更好地描述组件和它们之间的关系。</p> <p><strong>块(Block)</strong>:块是页面上的一个独立的、可复用的组件或模块,通常由一个父级元素包裹,并具有一个描述性的类名,用来表示这个块的名称。</p> <pre data-index="15" class="set-code-show" name="code"><code class="language-css hljs"><<span class="hljs-selector-tag">div</span> class="<span class="hljs-selector-tag">button</span>">...</<span class="hljs-selector-tag">div</span>> </code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>元素(Element)</strong>:元素是块的组成部分,它不能独立存在,必须与块相互关联。元素使用双下划线(__)来连接块的类名和元素的名称。</p> <pre data-index="16" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><<span class="hljs-selector-tag">div</span> class="<span class="hljs-selector-tag">button</span>"></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <<span class="hljs-selector-tag">span</span> class="button__text">Submit</<span class="hljs-selector-tag">span</span>></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"></<span class="hljs-selector-tag">div</span>></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>修饰符(Modifier)</strong>:修饰符是用来修改块或元素外观、状态或行为的类名。它们以单独的类名存在,通常使用单独的单短横线(-)来连接块或元素的类名和修饰符的名称。</p> <pre data-index="17" class="set-code-show" name="code"><code class="language-css hljs"><<span class="hljs-selector-tag">div</span> class="<span class="hljs-selector-tag">button</span> <span class="hljs-selector-tag">button</span><span class="hljs-attr">--primary</span>">...</<span class="hljs-selector-tag">div</span>> </code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <p><strong>7.什么是BFC?</strong></p> <blockquote> <p>BFC(Block Formatting Context)是CSS中的一个概念,它用于描述一个独立的渲染区域,其中元素的布局和渲染是相对于其他元素进行的。BFC是Web页面布局中的一个重要概念,它对元素的定位、清除浮动、边距折叠等方面都有重要影响。</p> <p>以下是关于BFC的一些关键特点和作用:</p> <ol><li> <p><strong>元素内部的独立容器</strong>: BFC会创建一个独立的渲染容器,使其内部的元素在布局上不受外部元素的影响。这意味着在一个BFC内部,元素的定位和布局是相对于BFC内部的内容进行的,而不会影响到外部元素。</p> </li><li> <p><strong>清除浮动</strong>: 当一个元素包含浮动元素时,它的高度可能会塌陷,不会包围浮动元素。但如果这个元素被设置为一个新的BFC,它将会包围浮动元素,解决了浮动元素导致的高度塌陷问题。</p> </li><li> <p><strong>边距折叠</strong>: 在BFC中,相邻元素的上下边距会发生折叠(margin collapse),这可以用于合并相邻元素的外边距。但是在不同的BFC中,边距不会折叠,因此BFC可以用来控制边距折叠的行为。</p> </li><li> <p><strong>阻止浮动元素溢出</strong>: 在BFC内部,浮动元素不会溢出到BFC的外部,而是会被包含在BFC内。</p> </li><li> <p><strong>强制分隔内容</strong>: BFC可以将页面分隔成不同的区域,这对于实现一些复杂的布局要求非常有用。</p> </li></ol> <p>要创建一个BFC,可以通过以下方式之一:</p> <ul><li>将元素的<code>overflow</code>属性设置为非默认值(例如,<code>overflow: auto;</code>或<code>overflow: hidden;</code>)。</li><li>将元素的<code>display</code>属性设置为<code>inline-block</code>、<code>table-cell</code>、<code>table-caption</code>、<code>flex</code>、<code>grid</code>等非默认值。</li><li>将元素的<code>position</code>属性设置为<code>absolute</code>或<code>fixed</code>。</li></ul> </blockquote> <p><strong>8.什么是粘性布局 ?</strong></p> <blockquote> <p>"粘性布局"(Sticky Layout)是一种用于网页布局的设计模式,它结合了固定定位(position: fixed)和相对定位(position: relative)的特性,使元素在页面上根据滚动位置实现不同的定位方式。</p> <p>粘性布局通常用于导航栏、侧边栏、工具栏等需要在页面滚动时保持在特定位置的元素。这种布局模式的主要特点是:</p> <ol><li> <p><strong>元素初始位置</strong>:元素在页面上的初始位置可以是普通文档流中的某个位置。</p> </li><li> <p><strong>滚动位置触发</strong>:当用户滚动页面,一旦元素的顶部(或底部)到达某个特定的滚动位置时,它会触发粘性定位,保持在那个位置不动。</p> </li><li> <p><strong>滚动结束还原</strong>:当用户继续滚动页面,直到元素的底部(或顶部)到达另一个特定的滚动位置时,元素将会取消粘性定位,并回到初始位置。</p> </li><li> <p><strong>不同滚动方向支持</strong>:粘性布局可以根据滚动方向(上滚或下滚)实现不同的粘性效果,例如,一个导航栏可以在用户向下滚动时固定在顶部,而在用户向上滚动时恢复到初始位置。</p> </li><li> <p><strong>使用 CSS <code>position</code> 属性</strong>:粘性布局通常使用 CSS 的 <code>position</code> 属性来实现,其中 <code>position: fixed</code> 用于固定定位,而 <code>position: relative</code> 用于相对定位。</p> </li></ol> <p>以下是一个简单的示例,展示了一个粘性导航栏的基本结构:</p> <pre data-index="18" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><<span class="hljs-selector-tag">div</span> class="navbar"></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <!-- 导航栏内容 --></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"></<span class="hljs-selector-tag">div</span>></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <pre data-index="19" class="set-code-show" name="code"><code class="language-css hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-class">.navbar</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">position</span>: relative; <span class="hljs-comment">/* 初始位置 */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-selector-class">.navbar</span><span class="hljs-selector-class">.sticky</span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">position</span>: fixed; <span class="hljs-comment">/* 粘性定位 */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>在这个示例中,当用户向下滚动页面时,通过 JavaScript 或 CSS 类添加 <code>.sticky</code> 类,从而将导航栏固定在顶部。当用户向上滚动并导航栏返回到初始位置时,移除 <code>.sticky</code> 类,取消粘性效果。</p> </blockquote> <h2><a name="t2"></a>三.JS篇</h2> <p><strong>1.JavaScript怎么判断数据的类型?</strong></p> <blockquote> <p>在JavaScript中,您可以使用多种方式来判断数据的类型。以下是一些常见的方法:</p> <p><strong>1.使用typeof运算符:</strong> <code>typeof</code> 运算符可以用于检查变量或值的数据类型。它返回一个表示数据类型的字符串。</p> <pre data-index="20" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-number">42</span>; <span class="hljs-comment">// 返回 "number"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-string">"Hello"</span>; <span class="hljs-comment">// 返回 "string"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// 返回 "boolean"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> {}; <span class="hljs-comment">// 返回 "object"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> []; <span class="hljs-comment">// 返回 "object"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-literal">null</span>; <span class="hljs-comment">// 返回 "object"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-literal">undefined</span>; <span class="hljs-comment">// 返回 "undefined"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">typeof</span> <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}; <span class="hljs-comment">// 返回 "function"</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p>需要注意的是,<code>typeof null</code> 返回 "object",这被认为是 JavaScript 中的一个历史 bug。</p> <p></p> <p><strong>2.使用instanceof运算符:</strong> <code>instanceof</code> 运算符可以用于检查一个对象是否属于特定的构造函数的实例。</p> <ol><li> <p><code>instanceof</code> 只能用于检查对象是否是由指定构造函数创建的实例。它不适用于原始数据类型,如数字、字符串和布尔值。</p> </li><li> <p><code>instanceof</code> 会遍历对象的原型链,因此如果对象的原型链上出现了指定构造函数,它也会返回 <code>true</code>。这可以用于检查继承关系。</p> </li><li> <p>要注意,如果你在多个窗口或框架中使用 <code>instanceof</code> 来检查对象类型,可能会出现问题,因为不同窗口或框架中的构造函数是不同的。</p> </li><li> <p>使用 <code>instanceof</code> 时,确保构造函数名首字母大写,因为构造函数通常以大写字母开头的命名规范</p> </li></ol> <pre data-index="21" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:780px"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> str = <span class="hljs-string">"Hello"</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(str <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">String</span>); <span class="hljs-comment">// 返回 false,因为 str 是一个原始字符串,不是 String 对象</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> arr = [];</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(arr <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>); <span class="hljs-comment">// 返回 true,因为 arr 是 Array 的实例</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">"John"</span> };</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(person <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Object</span>); <span class="hljs-comment">// 返回 true,因为 person 是 Object 的实例</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">function</span> <span class="hljs-title function_">Dog</span>(<span class="hljs-params"></span>) {}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> dog = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Dog</span>();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(dog <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Dog</span>); <span class="hljs-comment">// 返回 true,因为 dog 是 Dog 的实例</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>3.使用Object.prototype.toString方法:</strong> 这是一种更强大的方法,可以用于检查几乎所有数据类型,包括内置对象和自定义对象。</p> <pre data-index="22" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-number">42</span>); <span class="hljs-comment">// 返回 "[object Number]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-string">"Hello"</span>); <span class="hljs-comment">// 返回 "[object String]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-literal">true</span>); <span class="hljs-comment">// 返回 "[object Boolean]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>({}); <span class="hljs-comment">// 返回 "[object Object]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>([]); <span class="hljs-comment">// 返回 "[object Array]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-literal">null</span>); <span class="hljs-comment">// 返回 "[object Null]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-literal">undefined</span>); <span class="hljs-comment">// 返回 "[object Undefined]"</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">toString</span>.<span class="hljs-title function_">call</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>){}); <span class="hljs-comment">// 返回 "[object Function]"</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <p><strong>2.什么是类数组? </strong></p> <blockquote> <p>类数组(array-like object)是一种在 JavaScript 中常见的数据结构,它看起来像一个数组,但实际上是一个对象。这些对象通常具有数值键(整数索引),并且具有 <code>length</code> 属性,但它们不具备数组的所有方法和特性。</p> <p>以下是一些常见的类数组对象的特点:</p> <ol><li> <p><strong>有数值键:</strong> 类数组对象通常具有数值键,就像一个数组一样,您可以通过整数索引来访问元素。</p> </li><li> <p><strong>具有 length 属性:</strong> 类数组对象通常有一个 <code>length</code> 属性,该属性表示对象中元素的数量。</p> </li><li> <p><strong>不具备数组方法:</strong> 虽然类数组对象看起来像数组,但它们不具备数组的方法,例如 <code>push()</code>、<code>pop()</code>、<code>forEach()</code> 等。您不能直接使用这些方法。</p> </li><li> <p><strong>原型链上没有数组方法:</strong> 类数组对象的原型链通常不包含数组方法,这意味着您不能通过原型链访问数组方法。</p> </li></ol> <p> 要将类数组对象转换为真正的数组,您可以使用以下方法</p> <pre data-index="23" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> array = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(arrayLike);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> array = [...arrayLike];</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> array = [...arrayLike];</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">var</span> array = <span class="hljs-title class_">Array</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">slice</span>.<span class="hljs-title function_">call</span>(arrayLike);</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <p><strong>3.JS精度丢失问题是什么?怎么解决?</strong></p> <blockquote> <p>JavaScript 中的精度丢失问题通常与浮点数运算有关,这是因为 JavaScript 使用的是双精度浮点数表示数字,而不是精确的十进制表示法。这可能导致在某些情况下精度丢失,特别是在执行小数点后很多位的计算时。</p> <p>解决办法:</p> <p>1.转化成整数进行计算.</p> <p>2.使用专用的数学库:有一些第三方数学库,如 BigNumber.js 和 Decimal.js,可以提供更高精度的数学运算功能。</p> <p>3.四舍五入:在某些情况下,你可以通过四舍五入来处理小数精度问题,以获得符合预期的结果。JavaScript 提供了 <code>toFixed()</code> 方法来控制小数点后的位数,并且可以使用 <code>Math.round()</code> 等函数来进行四舍五入操作。</p> <p>4.小数点后的位数控制:在某些情况下,你可以通过限制小数点后的位数来避免精度丢失问题,以适应你的需求。这样可以减少计算中的精度问题。</p> </blockquote> <p><strong>4.JS内存泄漏的情况有那些? </strong></p> <blockquote> <p>JavaScript 中的内存泄漏是指不再使用的内存仍然被程序占用,而没有被垃圾回收机制释放。内存泄漏可能会导致应用程序变得越来越占用内存,最终可能导致程序性能下降或崩溃。以下是一些常见的导致 JavaScript 内存泄漏的情况:</p> <p><strong>未释放事件监听器</strong>:如果你在 DOM 元素上添加了事件监听器,但没有正确地移除它们,那么这些事件监听器会持续占用内存,即使元素已经被从 DOM 中移除。为了避免这种情况,你应该使用 <code>removeEventListener</code> 方法来移除事件监听器。</p> <pre data-index="24" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> button = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'myButton'</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">button.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, myFunction);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 错误的移除方式,会导致内存泄漏</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// button.removeEventListener('click', myFunction);</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 正确的移除方式</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">button.<span class="hljs-title function_">removeEventListener</span>(<span class="hljs-string">'click'</span>, myFunction);</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>闭包引用</strong>:当函数内部定义的变量被外部引用时,这个闭包可能会导致内存泄漏。如果闭包引用了大量的数据或长时间存活的对象,它们将不会被垃圾回收。</p> <pre data-index="25" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">function</span> <span class="hljs-title function_">createClosure</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Array</span>(<span class="hljs-number">1000000</span>).<span class="hljs-title function_">fill</span>(<span class="hljs-string">'memory'</span>); <span class="hljs-comment">// 大量数据</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 闭包引用了大量数据</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(data.<span class="hljs-property">length</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> };</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> closure = <span class="hljs-title function_">createClosure</span>();</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 即使不再使用 closure,但它仍然保留了对大量数据的引用,可能导致内存泄漏</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>定时器未清除</strong>:如果你使用 <code>setTimeout</code> 或 <code>setInterval</code> 创建了定时器,但忘记清除它们,定时器函数会继续执行,而不会释放相关资源。</p> <pre data-index="26" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 错误的方式,定时器未清除</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> timer = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =></span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'Interval function'</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}, <span class="hljs-number">1000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 正确的方式,清除定时器</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-built_in">clearInterval</span>(timer);</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>未释放不再需要的引用</strong>:在 JavaScript 中,当你不再需要某个对象或变量时,应该将其引用置为 <code>null</code>,以便让垃圾回收机制回收这些对象的内存。如果你保持不再需要的引用,那么这些对象将无法被释放。</p> <pre data-index="27" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">let</span> obj = { <span class="hljs-attr">data</span>: <span class="hljs-string">'some data'</span> };</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 当不再需要 obj 时,应该将其引用置为 null</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">obj = <span class="hljs-literal">null</span>;</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>循环引用</strong>:当两个或多个对象相互引用时,如果没有外部引用指向它们中的任何一个,那么它们将无法被垃圾回收,即使你不再需要它们。</p> <pre data-index="28" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> objA = {};</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> objB = {};</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">objA.<span class="hljs-property">ref</span> = objB;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">objB.<span class="hljs-property">ref</span> = objA;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment">// 即使不再需要 objA 和 objB,它们仍然相互引用,可能导致内存泄漏</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <p><strong>5.JS事件流和事件模型 </strong></p> <blockquote> <p>JavaScript 事件流和事件模型是用于处理和管理Web页面上发生的事件的关键概念。它们有助于理解事件是如何传播、捕获和处理的。事件模型通常有两种:冒泡事件模型和捕获事件模型。</p> <p><strong>事件流(Event Flow):</strong></p> <p> 事件流描述了事件从发生到被处理的整个过程。它可以分为三个阶段:</p> <ul><li> <p><strong>捕获阶段(Capture Phase)</strong>:事件从根元素开始向目标元素传播,这个阶段用于捕获事件,通常不太常用。</p> </li><li> <p><strong>目标阶段(Target Phase)</strong>:事件达到目标元素,也就是触发事件的元素。</p> </li><li> <p><strong>冒泡阶段(Bubble Phase)</strong>:事件从目标元素开始向根元素传播,这个阶段用于冒泡事件,通常是最常用的阶段。</p> </li></ul> <p>在标准的DOM事件模型中,事件首先进入捕获阶段,然后达到目标阶段,最后进入冒泡阶段。但大多数情况下,我们更关心冒泡阶段,因为它允许我们在父元素上捕获子元素的事件。</p> <p><strong>事件模型(Event Model)</strong>:</p> <p>事件模型定义了如何注册、捕获和处理事件的规则。有两种主要的事件模型:</p> <ul><li> <p><strong>冒泡事件模型(Bubbling Event Model)</strong>:在冒泡事件模型中,事件从目标元素开始冒泡,一直传播到根元素。这意味着父元素上的事件监听器会在子元素的事件监听器之前触发。</p> </li><li> <p><strong>捕获事件模型(Capturing Event Model)</strong>:在捕获事件模型中,事件从根元素开始捕获,一直传播到目标元素。这意味着父元素上的事件监听器会在子元素的事件监听器之后触发。</p> </li></ul> <p>大多数现代浏览器都支持冒泡事件模型,而捕获事件模型很少使用。你可以使用<code>addEventListener</code> 方法来注册事件监听器,然后选择是否使用冒泡或捕获。</p> </blockquote> <p><strong>6.JavaScript中this的指向 </strong></p> <blockquote> <p>JavaScript 中的 <code>this</code> 关键字是一个非常重要且常常令人困惑的概念,它指向当前执行上下文中的对象。<code>this</code> 的指向取决于函数是如何被调用的,以下是一些常见情况:</p> <p><strong>全局作用域中的 <code>this</code>:</strong> 在全局作用域(在任何函数外部)中,<code>this</code> 指向全局对象,通常是 <code>window</code> 对象(浏览器环境)。</p> <pre data-index="29" class="set-code-show" name="code"><code class="language-javascript hljs"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>); <span class="hljs-comment">// 在浏览器中,输出 window 对象</span> </code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>函数中的 <code>this</code>:</strong> 在函数内部,<code>this</code> 的值取决于函数的调用方式。以下是一些常见情况:</p> <ul><li><strong>作为函数调用:</strong> 当函数以普通函数的方式调用时,<code>this</code> 通常指向全局对象(在严格模式下是 <code>undefined</code>)。</li></ul> <pre data-index="30" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">function</span> <span class="hljs-title function_">myFunction</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>); <span class="hljs-comment">// 在浏览器中,输出 window 对象</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title function_">myFunction</span>();</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <ul><li> <strong>作为对象方法调用:</strong> 当函数作为对象的方法调用时,<code>this</code> 指向调用该方法的对象。</li></ul> <pre data-index="31" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> obj = {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>,</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">greet</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span>); <span class="hljs-comment">// 输出 'Alice'</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">};</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">obj.<span class="hljs-title function_">greet</span>();</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <ul><li> <strong>构造函数中的 <code>this</code>:</strong> 当使用 <code>new</code> 关键字调用构造函数时,<code>this</code> 指向新创建的对象。</li></ul> <pre data-index="32" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">function</span> <span class="hljs-title function_">Person</span>(<span class="hljs-params">name</span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = name;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> alice = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Person</span>(<span class="hljs-string">'Alice'</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(alice.<span class="hljs-property">name</span>); <span class="hljs-comment">// 输出 'Alice'</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <ul><li> <strong>使用 <code>call</code> 或 <code>apply</code> 方法:</strong> 可以使用 <code>call</code> 或 <code>apply</code> 方法显式地设置函数的 <code>this</code> 值。</li></ul> <pre data-index="33" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">function</span> <span class="hljs-title function_">sayHello</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Hello, <span class="hljs-subst">${<span class="hljs-variable language_">this</span>.name}</span>!`</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">}</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">'Bob'</span> };</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">sayHello.<span class="hljs-title function_">call</span>(person); <span class="hljs-comment">// 输出 'Hello, Bob!'</span></div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <ul><li> <strong>箭头函数中的 <code>this</code>:</strong> 箭头函数的 <code>this</code> 始终指向定义该箭头函数的外层函数的 <code>this</code> 值,而不是调用它的对象。</li></ul> <pre data-index="34" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">const</span> obj = {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>,</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">greet</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =></span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span>); <span class="hljs-comment">// 输出 'Alice'</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }, <span class="hljs-number">1000</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">};</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">obj.<span class="hljs-title function_">greet</span>();</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <h2 style="background-color:transparent;"><a name="t3"></a>四.Vue篇</h2> <p><strong>1.vue2的响应式原理</strong></p> <blockquote> <p>Vue.js 2.x 的响应式原理是基于"依赖追踪"和"发布-订阅模式"构建的。它的核心概念是Vue实例中的数据属性(data properties)如何与DOM元素建立关联,以便在数据变化时自动更新视图。</p> <p>以下是Vue 2.x 响应式原理的基本工作方式:</p> <p><strong>1.数据属性定义:</strong> 在Vue实例中,你通过<code>data</code>选项来定义数据属性。这些属性成为Vue实例的响应式数据。</p> <pre data-index="35" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">new</span> <span class="hljs-title class_">Vue</span>({</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">data</span>: {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-attr">message</span>: <span class="hljs-string">'Hello, Vue!'</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> }</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">})</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>2.依赖追踪:</strong> 当模板中的表达式引用数据属性时,Vue会在内部建立依赖关系。Vue跟踪哪些组件依赖哪些数据属性。这种追踪是静态的,即在模板编译阶段建立。</p> <pre data-index="36" class="set-code-show" name="code"><code class="language-javascript hljs"><div>{{ message }}</div> </code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> <p><strong>3.触发Getter(读取器):</strong> 当访问数据属性时,Vue会调用相应数据属性的Getter方法来获取数据的值,并将"观察者"(Watcher)添加到依赖列表中。</p> <p><strong>4.观察者(Watcher):</strong> 观察者是一个与依赖的数据属性相关联的对象,它会监听数据属性的变化。</p> <p><strong>5.数据变化时通知:</strong> 当数据属性发生变化时,Vue会触发Setter(写入器)方法来更新数据的值,然后通知相关的观察者。</p> <p><strong>6.视图更新:</strong> 观察者接收到通知后,会调用其自身的更新方法,这将导致相关的视图组件重新渲染,从而反映数据的变化。</p> <p>这个响应式系统使得数据和视图之间的关联变得非常紧密,而且不需要手动干预DOM。这也是Vue在开发过程中能够提供数据驱动视图的核心原因之一。</p> <p>需要注意的是,在Vue 2.x 中,这个响应式系统对于动态添加的属性(非初始属性)是无法响应的。如果需要动态添加属性并让其响应式,你可以使用<code>Vue.set</code>方法或<code>this.$set</code>方法来实现。</p> </blockquote> <p><strong>2.Vue数据双向绑定的原理</strong></p> <blockquote> <ol><li> <p><strong>数据劫持(Data Observation)</strong>:Vue使用了一个名为"数据劫持"的技术来追踪数据的变化。当你创建一个 Vue 实例时,Vue会遍历数据对象中的所有属性,使用 <code>Object.defineProperty</code> 方法将这些属性转换为"getter"和"setter"。这意味着当访问或修改数据属性时,Vue可以拦截这些操作,从而知道何时数据被访问或修改。</p> </li><li> <p><strong>虚拟 DOM(Virtual DOM)</strong>:Vue引入了虚拟 DOM 这个概念,它是一个虚拟的内存中的DOM表示。Vue的模板编译器将模板转换为虚拟 DOM 树。当数据发生变化时,Vue会比较新旧虚拟 DOM 树,找到需要更新的部分,然后仅更新这些部分,而不是重新渲染整个页面。</p> </li><li> <p><strong>Watcher 观察者</strong>:Vue还使用了Watcher(观察者)来建立视图和数据的连接。每个数据属性都有一个对应的观察者对象。当数据属性被访问时,Watcher 将记录该属性的依赖项,当属性发生变化时,Watcher 负责通知视图更新。</p> </li><li> <p><strong>Dep 依赖管理</strong>:每个观察者都有一个 Dep(依赖)对象,它用于管理依赖该观察者的所有数据属性。当一个数据属性被访问时,它会将该观察者添加到自己的依赖列表中,当属性变化时,它会通知所有依赖于它的观察者。</p> </li></ol> </blockquote> <p><strong>3.Vue3响应式原理</strong></p> <blockquote> <p>Vue 3 的响应式原理相对于 Vue 2 有一些重要的改进和优化,主要是通过 Proxy 对象和 Reflect API 来实现的。以下是 Vue 3 的响应式原理的主要特点:</p> <ol><li> <p><strong>Proxy 对象</strong>:Vue 3 使用了 JavaScript 的 Proxy 对象来替代 Vue 2 中的 Object.defineProperty,这使得响应式系统更加灵活和强大。Proxy 可以拦截对象上的各种操作,包括属性访问、属性赋值、属性删除等,而不仅仅是 get 和 set 操作。这使得 Vue 3 的响应式系统能够更精确地追踪属性的变化,而不仅仅是属性的读取和写入。</p> </li><li> <p><strong>Reactivity API</strong>:Vue 3 引入了新的 Reactivity API,允许开发者更灵活地创建和管理响应式数据。通过 <code>ref</code>、<code>reactive</code>、<code>toRefs</code> 等 API,你可以更容易地定义和处理响应式数据。例如,你可以使用 <code>ref</code> 来创建一个响应式的基本数据类型,或者使用 <code>reactive</code> 来创建一个响应式的对象。</p> </li><li> <p><strong>Composition API</strong>:Vue 3 推出了 Composition API,它使得组件的代码更具可组织性和可维护性。Composition API 允许你在组件内部自由组合和重用逻辑代码,而不再受限于 Vue 2 的选项对象格式。Composition API 的函数形式也更容易进行测试和调试。</p> </li><li> <p><strong>跨组件更新追踪</strong>:Vue 3 的响应式系统具有更好的跨组件更新追踪能力,这意味着当数据变化时,Vue 3 能够更有效地更新相关组件,减少不必要的渲染开销,提高了性能。</p> </li><li> <p><strong>缓存</strong>:Vue 3 引入了缓存机制,可以缓存计算属性和组件的渲染结果,减少不必要的重复计算和渲染,提高了性能。</p> </li></ol> </blockquote> <p><strong> 4.Vue组件生命周期</strong></p> <blockquote> <p>Vue.js 2.x 中的组件生命周期是一个非常重要的概念,它定义了组件在创建、挂载、更新和销毁等不同阶段所执行的钩子函数。以下是 Vue.js 2.x 组件生命周期的详细解析:</p> <ol><li> <p><strong>beforeCreate(创建前)</strong>:</p> <ul><li>钩子函数在实例被创建之后立即调用。</li><li>此时实例的数据观测和事件配置都尚未初始化。</li><li>不能访问 <code>data</code>、<code>props</code>、<code>computed</code> 或 <code>methods</code> 等属性或方法。</li></ul></li><li> <p><strong>created(创建后)</strong>:</p> <ul><li>钩子函数在实例被创建后立即调用。</li><li>此时实例已经完成数据观测和事件配置,但是尚未挂载到DOM上。</li><li>可以访问 <code>data</code>、<code>props</code>、<code>computed</code> 或 <code>methods</code> 等属性或方法。</li><li>常常用来进行异步操作,如发起网络请求或订阅事件。</li></ul></li><li> <p><strong>beforeMount(挂载前)</strong>:</p> <ul><li>钩子函数在实例被挂载到DOM之前立即调用。</li><li>此时虚拟DOM已经生成,但尚未渲染到页面上。</li></ul></li><li> <p><strong>mounted(挂载后)</strong>:</p> <ul><li>钩子函数在实例被挂载到DOM之后立即调用。</li><li>此时实例已经渲染到页面上,可以进行DOM操作。</li><li>常用于获取或操作DOM元素。</li></ul></li><li> <p><strong>beforeUpdate(更新前)</strong>:</p> <ul><li>钩子函数在数据更新后,但在虚拟DOM重新渲染和打补丁之前立即调用。</li><li>在此时可以访问到更新之前的DOM状态。</li><li>避免在此期间更改数据,以防进入无限循环。</li></ul></li><li> <p><strong>updated(更新后)</strong>:</p> <ul><li>钩子函数在数据更新后,虚拟DOM重新渲染和打补丁之后立即调用。</li><li>可以进行一些DOM操作,但要注意避免触发无限循环更新。</li></ul></li><li> <p><strong>beforeDestroy(销毁前)</strong>:</p> <ul><li>钩子函数在实例销毁之前立即调用。</li><li>可以在这里进行一些清理工作,如取消订阅、定时器等。</li><li>该阶段组件仍然完全可用。</li></ul></li><li> <p><strong>destroyed(销毁后)</strong>:</p> <ul><li>钩子函数在实例销毁之后立即调用。</li><li>所有的事件监听器和子组件实例都已经被销毁。</li><li>该阶段组件不再可用。</li></ul></li></ol> </blockquote> <p><strong>5.Vue中虚拟dom是什么?有什么作用?</strong></p> <blockquote> <p>在Vue.js中,虚拟DOM(Virtual DOM)是一种用于提高性能的技术。虚拟DOM是一个抽象的浏览器内存中的虚拟树,它与实际的DOM树相对应。Vue.js使用虚拟DOM来跟踪DOM树的状态变化,并最小化对实际DOM的操作,以提高性能和响应速度。</p> <p>虚拟DOM的作用包括以下几个方面:</p> <ol><li> <p>提高性能:虚拟DOM可以减少对实际DOM的直接操作次数。当数据变化时,Vue.js首先会在虚拟DOM中进行比较,找出需要更新的部分,然后将这些更新应用到实际DOM上。这个过程比直接操作实际DOM更高效,因为DOM操作通常是比较昂贵的。</p> </li><li> <p>简化复杂性:虚拟DOM允许开发者将视图的状态抽象为一个虚拟树,这样更容易理解和管理。开发者只需要关注数据的变化,而不需要手动操作DOM元素。</p> </li><li> <p>跨平台兼容性:虚拟DOM可以使Vue.js跨多个平台,例如浏览器、移动应用和服务器端渲染。通过不同的渲染器,Vue.js可以将虚拟DOM渲染成不同的输出。</p> </li><li> <p>实现高级特性:虚拟DOM也为Vue.js引入了一些高级特性,例如条件渲染、列表渲染和动画效果。这些特性可以更容易地实现,而无需手动处理DOM的复杂性。</p> </li></ol> <p>总之,虚拟DOM是Vue.js中的一个重要概念,它通过在内存中构建虚拟树来优化DOM操作,提高了应用程序的性能和可维护性,使开发者可以更专注于数据和应用逻辑而不是DOM操作。这使得Vue.js成为一个流行的前端框架之一。</p> </blockquote> <p><strong>6.Vue中组件通信的方式?</strong></p> <blockquote> <p>在Vue.js中,组件之间可以通过多种方式进行通信,具体的选择取决于你的应用需求和架构。以下是一些常见的组件通信方式:</p> <ol><li> <p><strong>Props 和 Events(父子组件通信)</strong>:</p> <ul><li>通过将数据通过props(属性)从父组件传递给子组件,子组件可以读取这些属性来显示数据。</li><li>子组件可以通过触发事件,使用<code>$emit</code>来通知父组件发生了某些事情,父组件可以监听这些事件并执行相应的操作。</li></ul></li><li> <p><strong>自定义事件</strong>:</p> <ul><li>使用Vue的实例方法<code>$on</code>和<code>$emit</code>,你可以创建自定义事件,使任何两个组件之间都可以进行通信。</li></ul></li><li> <p><strong>Vuex(状态管理)</strong>:</p> <ul><li>对于大型应用程序或需要多个组件之间共享状态的情况,可以使用Vuex来进行全局状态管理。Vuex提供了一个中央存储库,可以在任何组件中访问和修改应用程序的状态。</li></ul></li><li> <p><strong>$parent 和 $children</strong>:</p> <ul><li>Vue组件实例具有<code>$parent</code>和<code>$children</code>属性,允许你在组件树中的不同组件之间直接访问父组件和子组件。但要注意,这种方式通常被认为不太推荐,因为它会引入一定的耦合性。</li></ul></li><li> <p><strong>事件总线</strong>:</p> <ul><li>你可以创建一个简单的事件总线(Bus)来实现任何两个组件之间的通信。可以通过Vue实例作为中介来进行事件的触发和监听。</li></ul></li><li> <p><strong>Provide 和 Inject(祖先和后代组件通信)</strong>:</p> <ul><li>使用<code>provide</code>和<code>inject</code>选项,祖先组件可以向其后代组件提供数据,后代组件可以通过<code>inject</code>选项访问这些数据。</li></ul></li><li> <p><strong>全局事件总线</strong>:</p> <ul><li>你可以使用Vue的全局事件总线来实现跨组件通信。通过在Vue实例上使用<code>$on</code>和<code>$emit</code>来创建全局事件,任何组件都可以监听并触发这些事件。</li></ul></li><li> <p><strong>WebSocket 或其他通信协议</strong>:</p> <ul><li>如果需要跨组件、跨浏览器窗口或跨设备的实时通信,可以使用WebSocket或其他通信协议来建立双向通信。</li></ul></li></ol> <p>选择哪种通信方式取决于你的项目需求和组件之间的关系。通常,应该首先尝试使用Props和Events进行通信,然后根据需要引入更高级的通信方式,如Vuex或事件总线。</p> </blockquote> <p><strong>7.Vue中nextTick是什么?有什么作用 ?</strong></p> <blockquote> <p>在Vue.js中,<code>nextTick</code> 是一个重要的异步方法,用于在 Vue 实例更新DOM后执行回调函数。它的主要作用是确保你在更新数据后立即操作DOM元素,而不必担心数据更新是否已经同步到DOM中。</p> <p>具体来说,<code>nextTick</code> 的作用包括:</p> <ol><li> <p>异步更新DOM:Vue的数据更新是异步的,当你修改了数据时,Vue并不会立即更新DOM。而使用<code>nextTick</code>,你可以在下一轮事件循环中确保DOM已经更新,然后再执行你的回调函数。这对于在数据变化后操作DOM非常有用,因为你不需要手动等待DOM更新完成。</p> </li><li> <p>避免重复操作:有时候你可能需要在同一个事件循环中多次修改数据,如果不使用<code>nextTick</code>,可能会导致不必要的重复操作DOM。使用<code>nextTick</code>可以确保在同一事件循环中所有的数据更新都已经完成。</p> </li><li> <p>执行一些特定的DOM操作:在某些情况下,你可能需要在Vue实例更新DOM后立即执行一些特定的DOM操作,例如获取元素的尺寸、位置或焦点等。<code>nextTick</code>让你能够确保这些DOM操作在数据更新后进行。</p> </li></ol> <pre data-index="37" class="set-code-show" name="code"><code class="language-javascript hljs"><ol class="hljs-ln" style="width:100%"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">import</span> { nextTick } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-title function_">nextTick</span>(<span class="hljs-function">() =></span> {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">// 这里的代码会在 DOM 更新后执行</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'DOM updated'</span>)</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">})</div></div></li></ol></code><div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}" onclick="hljs.signin(event)"></div></pre> </blockquote> <p><strong>8.Vue中v-for的key的作用 </strong></p> <blockquote> <p>在Vue.js中,<code>v-for</code>指令用于循环渲染一个数组或对象的元素,它会为每个循环的元素创建一个新的Vue实例或虚拟DOM节点。<code>key</code>属性是用来帮助Vue跟踪每个循环元素的特定身份,以便在数据发生变化时能够高效地更新DOM。</p> <p><code>key</code>属性的作用包括:</p> <ol><li> <p>提高性能:当数据发生变化时,Vue使用<code>key</code>来识别哪些元素是新增的、删除的或重排的。如果没有提供<code>key</code>,Vue可能会采用默认的机制来尝试识别元素的身份,这可能会导致性能下降,因为Vue需要更多的计算来确定元素的变化。</p> </li><li> <p>防止重复渲染:当使用<code>v-for</code>循环渲染相似的元素列表时,为每个元素提供唯一的<code>key</code>可以确保Vue不会错误地重用之前渲染的元素状态,从而避免潜在的错误和不一致。</p> </li><li> <p>方便的动画过渡:如果你使用Vue的过渡效果,<code>key</code>属性还可以帮助Vue正确地应用过渡效果,以便在元素被添加或删除时产生流畅的动画。</p> </li></ol> <p>在使用<code>v-for</code>时,通常建议为每个循环的元素提供一个唯一的<code>key</code>,这个<code>key</code>可以是一个字符串或数字,通常使用循环元素的唯一标识符。</p> </blockquote> <h2><a name="t4"></a><strong>五.webpack篇 </strong></h2> <p><strong>1.chunk是什么?</strong></p> <blockquote> <p>在Webpack中,"chunk"(代码块)是指将 JavaScript 代码分割成小块的一种技术。Webpack允许你将应用程序的代码拆分成多个文件,每个文件被称为一个代码块(chunk)。这个功能有助于减小单个 JavaScript 文件的大小,提高应用程序的性能,特别是在大型应用中。</p> <p>Webpack中的"chunk"通常有两种类型:</p> <ol><li> <p><strong>Entry Chunk(入口代码块):</strong> 这是由Webpack配置文件中的入口点(entry point)定义的代码块。入口点是你应用程序的起点,Webpack从这里开始分析依赖关系,然后将所有相关的模块打包到一个或多个入口代码块中。通常,一个应用程序会有一个或多个入口点,每个入口点生成一个入口代码块。</p> </li><li> <p><strong>Split Chunk(拆分代码块):</strong> 这是通过Webpack的代码分割(code splitting)功能生成的代码块。代码分割允许你按需加载(lazy load)代码,将不同部分的代码拆分成独立的代码块,以减少初始加载时间。拆分代码块可以根据不同的条件生成,比如按照模块的共享性质、大小等。</p> </li></ol> <p>通过使用Webpack的代码块功能,你可以更好地管理你的应用程序的代码,优化性能,以及实现按需加载,从而提高用户体验。通过合理配置Webpack的代码块策略,你可以控制生成的代码块的数量和大小,以满足你的项目需求。</p> </blockquote> <p><strong>2.loader是什么?</strong></p> <blockquote> <p>在Webpack和许多其他前端构建工具中,"loader" 是一种用于对不同类型文件进行转换和处理的插件。Loader允许你在导入或加载文件时对它们进行预处理,以便在项目中使用。</p> <p>以下是Loader的一些关键特点和用途:</p> <ol><li> <p><strong>文件转换:</strong> Loader用于将不同类型的文件(例如JavaScript、CSS、图片、字体等)转换成可以被应用程序理解的格式。例如,使用Babel Loader可以将ES6/ES7的JavaScript代码转换为ES5,以便在旧版浏览器中运行。</p> </li><li> <p><strong>模块化:</strong> Loader可以将资源文件转换成模块,使其可以通过import语句在代码中引用。这种模块化的特性对于将CSS样式或图片等资源与特定组件或模块关联非常有用。</p> </li><li> <p><strong>链式处理:</strong> 你可以使用多个Loader来创建一个Loader链,每个Loader都按照一定顺序依次处理文件。这使得你可以在项目中执行多个转换步骤,例如首先使用Sass Loader编译Sass文件,然后使用CSS Loader处理CSS文件,最后使用Style Loader将CSS样式注入到HTML中。</p> </li><li> <p><strong>自动解析依赖关系:</strong> Loader可以自动解析文件之间的依赖关系,确保在需要时自动加载依赖的模块或资源。</p> </li><li> <p><strong>配置灵活:</strong> Loader通常可以通过Webpack配置文件的配置项来进行自定义和调整。这使得你可以根据项目需求来配置Loader的行为。</p> </li></ol> </blockquote> <p><strong>3.常用的loader?</strong></p> <blockquote> <p>以下是一些常用的Webpack Loader及其作用:</p> <ol><li> <p><strong>babel-loader:</strong> 用于处理JavaScript文件,特别是新的ECMAScript标准(如ES6、ES7等)。它将现代JavaScript代码转换为向后兼容的代码,以便在旧版浏览器中运行。</p> </li><li> <p><strong>css-loader 和 style-loader:</strong> 用于处理CSS文件。css-loader负责解析CSS文件,处理CSS模块化,并解决依赖关系,而style-loader则将CSS样式以<code><style></code>标签的形式注入到HTML中,使样式生效。</p> </li><li> <p><strong>sass-loader 和 less-loader:</strong> 用于处理Sass和Less等CSS预处理器的文件。它们将Sass或Less代码编译成普通的CSS,以便浏览器可以理解。</p> </li><li> <p><strong>file-loader 和 url-loader:</strong> 用于处理文件资源,如图片、字体等。file-loader负责复制文件到输出目录,并返回文件的路径,而url-loader可以将小文件编码成DataURL,以减少HTTP请求的数量。</p> </li><li> <p><strong>image-loader:</strong> 用于处理图片文件,压缩和优化图像,并返回图像的URL。</p> </li><li> <p><strong>json-loader:</strong> 用于加载和解析JSON文件。</p> </li><li> <p><strong>csv-loader 和 xml-loader:</strong> 用于加载和解析CSV和XML文件。</p> </li><li> <p><strong>raw-loader:</strong> 将文件内容作为字符串导出,通常用于加载文本文件。</p> </li><li> <p><strong>url-loader:</strong> 与file-loader类似,但具有更高级的功能。它可以将小文件转换为DataURL,以减少HTTP请求的数量。</p> </li><li> <p><strong>eslint-loader 和 stylelint-loader:</strong> 用于集成ESLint和Stylelint等代码质量检查工具,可以在构建过程中检查代码并报告问题。</p> </li><li> <p><strong>vue-loader:</strong> 用于处理Vue.js单文件组件(.vue文件),将其解析成可用的JavaScript模块。</p> </li><li> <p><strong>ts-loader:</strong> 用于处理TypeScript文件,将TypeScript代码转换为JavaScript。</p> </li><li> <p><strong>postcss-loader:</strong> 用于处理CSS后处理器,如Autoprefixer,以自动添加CSS前缀和其他处理。</p> </li><li> <p><strong>html-loader:</strong> 用于处理HTML文件,可以将HTML文件导出为字符串,也可以处理HTML中的资源链接。</p> </li></ol> </blockquote> <p><strong>4.Plugins是什么? </strong></p> <blockquote> <p>在Webpack中,插件(Plugin)是用于执行各种构建任务和自定义构建过程的工具。Webpack插件是基于事件机制工作的,它们可以监听Webpack构建过程的不同阶段并执行特定的任务,从而扩展或修改Webpack的功能。插件通常用于处理一些复杂的任务,如代码压缩、资源优化、环境变量注入、HTML生成等等。</p> <p>以下是一些Webpack中常用的插件以及它们的作用:</p> <ol><li> <p><strong>HtmlWebpackPlugin:</strong> 用于生成HTML文件,并自动将打包后的JavaScript和CSS文件注入到HTML中。</p> </li><li> <p><strong>CleanWebpackPlugin:</strong> 用于清理构建目录,以确保每次构建之前都可以清除旧的文件。</p> </li><li> <p><strong>MiniCssExtractPlugin:</strong> 用于将CSS代码从JavaScript中提取出来,并生成独立的CSS文件,以加快页面加载速度。</p> </li><li> <p><strong>OptimizeCssAssetsWebpackPlugin:</strong> 用于优化和压缩CSS文件。</p> </li><li> <p><strong>TerserWebpackPlugin:</strong> 用于优化和压缩JavaScript代码。</p> </li><li> <p><strong>DefinePlugin:</strong> 用于在编译时注入全局变量,可以用于配置不同的环境,如开发环境和生产环境。</p> </li><li> <p><strong>CopyWebpackPlugin:</strong> 用于复制静态文件(如图片、字体等)到构建输出目录。</p> </li><li> <p><strong>ProvidePlugin:</strong> 自动加载模块,无需在代码中手动导入,常用于引入全局库或工具函数。</p> </li><li> <p><strong>BundleAnalyzerPlugin:</strong> 用于可视化分析构建生成的包文件大小,有助于优化打包结果。</p> </li><li> <p><strong>HotModuleReplacementPlugin:</strong> 用于实现热模块替换(HMR),在开发过程中实现模块的无刷新更新。</p> </li><li> <p><strong>SplitChunksPlugin:</strong> 用于配置代码分割(Code Splitting),将公共模块提取出来以减少代码重复加载。</p> </li><li> <p><strong>ProvidePlugin:</strong> 用于自动加载模块,无需在代码中手动导入,常用于引入全局库或工具函数。</p> </li></ol> <p>这些插件可以通过Webpack配置文件中的<code>plugins</code>选项进行配置和启用。通常,一个Webpack配置文件中可以同时使用多个插件,以满足不同的需求和场景。插件是Webpack非常强大和灵活的扩展机制,使得你可以对构建过程进行高度定制和优化。</p> </blockquote> <p><strong>5.什么是依赖图? </strong></p> <blockquote> <p>每当一个文件依赖另一个文件时,webpack 都会将文件视为直接存在 <em>依赖关系</em>。这使得 webpack 可以获取非代码资源,如 images 或 web 字体等。并会把它们作为 <em>依赖</em> 提供给应用程序。</p> <p>当 webpack 处理应用程序时,它会根据命令行参数中或配置文件中定义的模块列表开始处理。 从 <a href="https://www.webpackjs.com/concepts/entry-points/" rel="nofollow" title="入口">入口</a> 开始,webpack 会递归的构建一个 <em>依赖关系图</em>,这个依赖图包含着应用程序中所需的每个模块,然后将所有模块打包为少量的 <em>bundle</em> —— 通常只有一个 —— 可由浏览器加载。</p> </blockquote> <p><strong>6.什么是HMR? </strong></p> <blockquote> <p>HMR(Hot Module Replacement,热模块替换)是一种前端开发工具,用于在应用程序运行时无需完全刷新页面即可实时更新代码和模块。HMR可以极大地提高开发效率,因为它允许开发者在不中断应用程序状态的情况下进行代码编辑和调试。</p> <p>HMR的工作原理如下:</p> <ol><li> <p>当你启动开发服务器或运行开发模式的应用程序时,Webpack会将模块的热更新功能添加到代码中。</p> </li><li> <p>当你修改了一个模块的代码时,Webpack会构建新的模块版本。</p> </li><li> <p>新的模块版本会与当前运行的应用程序进行比较。</p> </li><li> <p>如果发现模块有变化,HMR会在不刷新整个页面的情况下,将新的模块代码替换到应用程序中。这样,你可以立即看到代码更改的效果,同时保持应用程序的状态(例如表单输入、当前路由等)不受影响。</p> </li></ol> <p>HMR对于开发大型单页应用程序或复杂的前端项目特别有用,因为它可以大大减少开发周期中的刷新时间,提供更快的反馈循环。它通常与开发服务器一起使用,例如Webpack Dev Server,以便自动启用HMR功能。</p> </blockquote> <h2><a name="t5"></a>六.网络篇 </h2> <p><strong>1.解释HTTP和HTTPS的区别。</strong></p> <blockquote> <p>HTTP(Hypertext Transfer Protocol)和HTTPS(Hypertext Transfer Protocol Secure)是两种用于传输数据的网络协议,它们之间的主要区别在于安全性:</p> <ol><li> <p><strong>安全性</strong>:</p> <ul><li><strong>HTTP</strong>:HTTP是一种不安全的协议,它的通信数据是明文传输的,容易被中间人窃听和篡改。这意味着敏感信息(如密码、信用卡号等)在传输过程中容易被黑客截取。</li><li><strong>HTTPS</strong>:HTTPS通过使用SSL/TLS(Secure Sockets Layer/Transport Layer Security)协议来保护数据的安全性。它使用加密技术对通信数据进行加密,使数据传输过程中更难以被窃听或篡改。因此,HTTPS更适合于保护敏感信息的传输,例如在网上购物或登录时。</li></ul></li><li> <p><strong>证书</strong>:</p> <ul><li><strong>HTTP</strong>:HTTP不涉及证书验证,任何人都可以建立HTTP连接,而不需要证明其身份。</li><li><strong>HTTPS</strong>:HTTPS需要使用SSL/TLS证书,这些证书由受信任的第三方机构(称为证书颁发机构,CA)颁发。这些证书用于验证网站的身份,确保用户连接到的是合法和受信任的网站。当你访问一个使用HTTPS的网站时,浏览器会检查网站的SSL/TLS证书是否有效,如果证书无效或已被吊销,浏览器会发出警告。</li></ul></li><li> <p><strong>端口</strong>:</p> <ul><li><strong>HTTP</strong>:HTTP默认使用端口80进行通信。</li><li><strong>HTTPS</strong>:HTTPS默认使用端口443进行通信。如果在URL中不指定端口号,浏览器会自动将请求发送到443端口。</li></ul></li><li> <p><strong>URL前缀</strong>:</p> <ul><li><strong>HTTP</strong>:HTTP的URL以<code>http://</code>开头。</li><li><strong>HTTPS</strong>:HTTPS的URL以<code>https://</code>开头。</li></ul></li></ol> <p>总结来说,HTTP和HTTPS之间的主要区别在于安全性。HTTPS通过数据加密和证书验证提供了更高级别的安全性,因此在需要保护用户隐私和数据完整性的情况下应优先选择HTTPS。在今天的互联网中,许多网站都采用HTTPS,以确保用户的敏感信息得到保护。</p> </blockquote> <p><strong>2.什么是HTTP方法(GET、POST、PUT、DELETE等),它们的用途是什么? </strong></p> <blockquote> <p>HTTP方法是用于定义客户端与服务器之间进行通信的动作或操作类型的标准化规范。每个HTTP方法都对应于不同的操作,用于执行不同的任务。以下是常见的HTTP方法及其主要用途:</p> <ol><li> <p><strong>GET</strong>:</p> <ul><li><strong>用途</strong>:GET方法用于从服务器获取资源,通常用于向服务器请求数据。它是一种幂等方法,即多次重复相同的GET请求不会对服务器产生副作用,不会改变资源的状态。</li><li><strong>示例</strong>:获取网页、图像、JSON数据等。</li></ul></li><li> <p><strong>POST</strong>:</p> <ul><li><strong>用途</strong>:POST方法用于向服务器提交数据,通常用于创建新资源或在服务器上执行非幂等操作,如提交表单数据、上传文件等。POST请求可能会导致服务器状态的改变。</li><li><strong>示例</strong>:提交表单数据、发布新文章、上传文件等。</li></ul></li><li> <p><strong>PUT</strong>:</p> <ul><li><strong>用途</strong>:PUT方法用于更新服务器上的资源,通常用于替换服务器上的资源或创建新资源,如果资源不存在则创建。它是幂等的,即多次重复相同的PUT请求应该具有相同的效果。</li><li><strong>示例</strong>:更新用户信息、编辑文章内容等。</li></ul></li><li> <p><strong>DELETE</strong>:</p> <ul><li><strong>用途</strong>:DELETE方法用于删除服务器上的资源,通常用于删除指定的资源。它是幂等的,多次重复相同的DELETE请求应该具有相同的效果。</li><li><strong>示例</strong>:删除用户、删除文件等。</li></ul></li><li> <p><strong>PATCH</strong>:</p> <ul><li><strong>用途</strong>:PATCH方法用于部分更新服务器上的资源,通常用于对资源进行局部修改而不是替换整个资源。它是幂等的,多次重复相同的PATCH请求应该具有相同的效果。</li><li><strong>示例</strong>:修改用户信息的某个字段、修改文章的部分内容等。</li></ul></li><li> <p><strong>HEAD</strong>:</p> <ul><li><strong>用途</strong>:HEAD方法类似于GET方法,但不返回实际的响应主体,只返回响应头信息。它通常用于检查资源的元信息,如是否存在、最后修改时间等,而无需实际获取资源内容。</li><li><strong>示例</strong>:检查资源是否存在、获取资源的元信息等。</li></ul></li><li> <p><strong>OPTIONS</strong>:</p> <ul><li><strong>用途</strong>:OPTIONS方法用于获取服务器支持的HTTP方法列表以及资源的元信息。它通常用于跨域请求中的预检请求(preflight requests)。</li><li><strong>示例</strong>:获取服务器支持的方法、检查跨域请求是否允许等。</li></ul></li></ol> <p>这些HTTP方法定义了不同的操作,使客户端能够与服务器进行各种类型的交互。了解每种方法的用途和特性有助于开发者根据应用程序的需求选择合适的方法来进行HTTP请求。</p> </blockquote> <p><strong>3.HTTP状态码的含义,例如200、404、500等。 </strong></p> <blockquote> <p>HTTP状态码是服务器响应HTTP请求时返回的三位数字代码,用于表示请求的处理结果。这些状态码可以帮助客户端了解服务器的响应情况,并采取相应的行动。以下是一些常见的HTTP状态码及其含义:</p> <ol><li> <p><strong>1xx(信息性状态码)</strong>:</p> <ul><li><strong>100 Continue</strong>:服务器已经收到了请求的头部,并且客户端应该继续发送请求的主体部分。</li><li><strong>101 Switching Protocols</strong>:服务器已经理解客户端的请求,将切换到协议升级。</li></ul></li><li> <p><strong>2xx(成功状态码)</strong>:</p> <ul><li><strong>200 OK</strong>:请求成功,服务器已经返回请求的数据。</li><li><strong>201 Created</strong>:请求成功,服务器创建了新的资源。</li><li><strong>204 No Content</strong>:请求成功,服务器已经成功处理了请求,但没有返回任何内容。</li></ul></li><li> <p><strong>3xx(重定向状态码)</strong>:</p> <ul><li><strong>301 Moved Permanently</strong>:请求的资源已永久移动到新的URL。</li><li><strong>302 Found</strong>:请求的资源临时移动到新的URL。</li><li><strong>304 Not Modified</strong>:客户端请求的资源未修改,可以使用缓存的版本。</li></ul></li><li> <p><strong>4xx(客户端错误状态码)</strong>:</p> <ul><li><strong>400 Bad Request</strong>:客户端发送的请求有错误,服务器无法理解。</li><li><strong>401 Unauthorized</strong>:请求需要用户身份验证。</li><li><strong>403 Forbidden</strong>:服务器拒绝请求,没有权限访问请求的资源。</li><li><strong>404 Not Found</strong>:请求的资源不存在。</li><li><strong>429 Too Many Requests</strong>:请求频率过高,触发了服务器的限速机制。</li></ul></li><li> <p><strong>5xx(服务器错误状态码)</strong>:</p> <ul><li><strong>500 Internal Server Error</strong>:服务器内部发生错误,无法完成请求。</li><li><strong>502 Bad Gateway</strong>:服务器作为网关或代理接收到无效响应。</li><li><strong>503 Service Unavailable</strong>:服务器当前无法处理请求,通常是临时性的维护或过载。</li><li><strong>504 Gateway Timeout</strong>:服务器作为网关或代理未能及时收到响应。</li></ul></li></ol> <p>这些HTTP状态码提供了关于请求和响应状态的信息,帮助客户端和服务器进行通信和故障排除。开发者可以根据状态码来调试和修复问题,以确保良好的网络通信和用户体验。</p> </blockquote> <p><strong>4.什么是TCP和UDP协议?它们有什么区别? </strong></p> <blockquote> <p>TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)都是计算机网络中常见的传输层协议,用于在不同设备之间传输数据。它们有一些关键的区别:</p> <p><strong>TCP(传输控制协议):</strong></p> <ol><li> <p><strong>可靠性</strong>:TCP是一种可靠的协议,它确保数据的完整性和可靠性。它通过序号、确认和重传机制来确保数据包按顺序到达并且不丢失。</p> </li><li> <p><strong>连接导向</strong>:TCP是面向连接的协议,通信的双方必须在通信之前建立连接。这种连接通常包括三次握手和四次挥手过程,用于建立和终止连接。</p> </li><li> <p><strong>流控制</strong>:TCP使用流控制机制,以避免发送方发送过多数据导致接收方无法处理的情况。</p> </li><li> <p><strong>拥塞控制</strong>:TCP具有拥塞控制机制,用于在网络拥塞时减少发送速率以避免丢失数据包。</p> </li><li> <p><strong>适用场景</strong>:TCP适用于需要可靠数据传输的应用,如网页浏览、电子邮件、文件传输等,以及需要按顺序传输数据的应用。</p> </li></ol> <p><strong>UDP(用户数据报协议):</strong></p> <ol><li> <p><strong>不可靠性</strong>:UDP是一种不可靠的协议,它不提供数据的完整性和可靠性。数据包可以在传输过程中丢失、乱序或重复。</p> </li><li> <p><strong>无连接</strong>:UDP是无连接的,通信的双方不需要建立连接。每个数据包都是独立的,没有关联性。</p> </li><li> <p><strong>不支持流控制和拥塞控制</strong>:UDP不提供流控制和拥塞控制机制。发送方会尽力发送数据,而不管接收方是否能够跟上。</p> </li><li> <p><strong>适用场景</strong>:UDP适用于那些对数据传输的实时性要求更高、可以容忍一定数据丢失的应用,如音频和视频流、在线游戏、实时通信应用等。</p> </li></ol> <p>总结来说,TCP和UDP是两种不同的传输协议,适用于不同的应用场景。TCP提供了可靠的、面向连接的通信,适合需要确保数据完整性和可靠性的应用。而UDP提供了不可靠的、无连接的通信,适合那些需要快速传输并可以容忍一定数据丢失的应用。选择使用哪种协议取决于应用的特定需求。</p> </blockquote> <p><strong>5.使用CDN(内容分发网络)的好处。 </strong></p> <blockquote> <p>内容分发网络(CDN)是一种将网站或应用程序的内容分发到全球多个服务器位置的网络基础设施。CDN的主要目标是提供更快、更可靠的内容传递,同时减轻源服务器的负担。以下是使用CDN的一些主要好处:</p> <ol><li> <p><strong>提高性能和加载速度</strong>:</p> <ul><li>CDN服务器通常位于全球各个地理位置,使内容更接近最终用户。这意味着用户可以从距离更近的服务器获取内容,从而减少延迟和提高加载速度。</li><li>CDN使用高度优化的网络和服务器基础设施,通常可以更有效地处理请求,从而提供更快的响应时间。</li></ul></li><li> <p><strong>减轻源服务器负担</strong>:</p> <ul><li>CDN充当了缓存层,可以缓存和提供静态资源,如图像、样式表和JavaScript文件。这减轻了源服务器的负载,使其能够更好地处理动态请求。</li><li>针对恶意攻击(例如分布式拒绝服务攻击)的CDN可以过滤和缓解流量,保护源服务器免受攻击。</li></ul></li><li> <p><strong>全球可用性和冗余</strong>:</p> <ul><li>CDN的多个服务器位置意味着即使其中一个服务器出现故障,用户仍然可以从其他服务器获取内容,提高了可用性和冗余性。</li><li>在全球各地部署CDN可以确保内容在不同地区的用户之间分布均匀,提供更好的用户体验。</li></ul></li><li> <p><strong>降低带宽成本</strong>:</p> <ul><li>CDN通常可以提供较低的带宽费用,因为它们具有高度优化的网络架构和大量的服务器资源。</li><li>减少了数据从源服务器到终端用户的传输距离,从而减少了带宽成本。</li></ul></li><li> <p><strong>安全性</strong>:</p> <ul><li>一些CDN提供安全功能,如DDoS攻击防护、SSL加密、内容验证和访问控制,以提高网站和应用程序的安全性。</li></ul></li><li> <p><strong>易于管理和扩展</strong>:</p> <ul><li>使用CDN通常是相对简单的,可以轻松地配置和管理。CDN提供了用于监视和控制内容传递的工具和仪表板。</li><li>当需要扩展到新的地理位置或处理更多的流量时,CDN提供了弹性和可伸缩性。</li></ul></li></ol> <p>总的来说,CDN可以显著提高网站和应用程序的性能、可用性和安全性,减少了源服务器的负担,同时也有助于降低带宽成本。这使得CDN成为许多互联网公司的重要基础设施组成部分,特别是对于需要全球范围内快速交付内容的网站和应用程序。</p> </blockquote> <p><strong>6.SPA的优点和缺点。 </strong></p> <blockquote> <p>单页面应用(SPA,Single Page Application)是一种Web应用程序架构,其中所有页面加载一次,然后通过AJAX或WebSockets等技术动态地更新页面内容,而不需要每次用户导航时都重新加载整个页面。SPA具有一些优点和缺点:</p> <p><strong>优点:</strong></p> <ol><li> <p><strong>更快的用户体验</strong>:</p> SPA通过在用户与页面之间切换时减少页面刷新,提供了更快的加载速度和更流畅的用户体验,因为大部分页面内容都在首次加载时获取。</li><li> <p><strong>减少服务器负载</strong>:</p> 由于SPA在首次加载后只需要从服务器获取数据而不是整个页面,所以可以减轻服务器的负载,减少带宽使用,提高服务器的性能。</li><li> <p><strong>前后端分离</strong>:</p> SPA通常采用前后端分离的架构,前端和后端可以独立开发、测试和维护,使团队协作更加灵活。</li><li> <p><strong>富交互性</strong>:</p> SPA允许在单个页面上实现复杂的交互和动画效果,提供更富交互性的用户界面,增强了用户吸引力。</li><li> <p><strong>路由控制</strong>:</p> SPA通常使用客户端路由来管理页面之间的导航,这使得在页面之间切换更为灵活,无需向服务器发起请求。</li></ol> <p><strong>缺点:</strong></p> <ol><li> <p><strong>首次加载时间较长</strong>:</p> SPA的首次加载通常需要下载所有必要的HTML、JavaScript和CSS文件,这可能导致较长的等待时间,尤其是在较慢的网络连接下。</li><li> <p><strong>SEO问题</strong>:</p> 由于SPA在首次加载时通常只包含少量HTML内容,搜索引擎可能难以正确索引页面内容,导致SEO方面的挑战。尽管可以通过预渲染技术和服务端渲染来解决这个问题,但需要额外的工作。</li><li> <p><strong>复杂性</strong>:</p> SPA通常需要复杂的前端路由和状态管理,这可能增加开发的复杂性和学习曲线。</li><li> <p><strong>浏览器兼容性</strong>:</p> 一些老版本的浏览器可能不支持HTML5的一些特性,导致SPA在这些浏览器中运行不稳定或不兼容。</li><li> <p><strong>内存管理</strong>:</p> SPA在长时间使用中可能会积累大量JavaScript对象,需要额外的内存管理和性能优化来确保页面的性能。</li></ol> <p>综上所述,SPA在提供更好的用户体验和开发灵活性方面具有明显的优点,但也存在一些挑战,如首次加载时间、SEO问题和复杂性。选择使用SPA或传统多页面应用应根据项目需求和目标来决定。</p> </blockquote> <p><strong>7.什么是懒加载和预加载? </strong></p> <blockquote> <p>懒加载(Lazy Loading)和预加载(Preloading)是网页性能优化的两种策略,用于改善页面加载速度和用户体验。它们的作用和实现方式有所不同:</p> <p><strong>懒加载(Lazy Loading)</strong>:</p> <p>懒加载是一种延迟加载页面内容或资源的技术,只有当用户需要访问特定部分或资源时,才会加载它们。懒加载通常应用于以下情况:</p> <ol><li> <p><strong>图片懒加载</strong>:在Web页面中,图片是常见的懒加载目标。当页面加载时,只加载可视区域内的图片,而不加载页面上的所有图片。这可以减少初始页面加载时间。</p> </li><li> <p><strong>无限滚动</strong>:在滚动页面时,懒加载可以用于加载更多内容,例如在社交媒体网站上加载新的帖子或在产品目录中加载更多产品。</p> </li><li> <p><strong>动态加载组件</strong>:在单页面应用(SPA)或异步加载的情况下,可以采用懒加载策略,仅在需要时加载组件、模块或页面。</p> </li></ol> <p><strong>预加载(Preloading)</strong>:</p> <p>预加载是一种在页面加载过程中提前加载某些资源的技术,以便在用户需要访问它们时能够更快地获取。预加载通常应用于以下情况:</p> <ol><li> <p><strong>提前加载资源</strong>:通过添加<code><link></code>标签或JavaScript代码,可以提前加载可能在后续页面中使用的关键资源,如CSS文件、JavaScript文件、字体等。这有助于减少页面切换时的加载延迟。</p> </li><li> <p><strong>预取数据</strong>:对于一些需要动态加载数据的情况,可以在用户需要之前提前获取数据,以便在用户请求时能够立即显示。这可以提高用户体验,尤其是在网页应用程序中。</p> </li><li> <p><strong>DNS预解析</strong>:浏览器可以通过DNS预解析来提前解析与当前页面相关的域名,以减少后续资源加载的延迟。这可以通过<code><link rel="dns-prefetch"></code>标签来实现。</p> </li></ol> <p>需要注意的是,虽然懒加载和预加载都可以提高页面性能,但它们应根据具体的应用场景和用户需求来合理使用。滥用懒加载可能会导致用户在浏览页面时出现内容突然加载的不连贯感,而滥用预加载可能会增加额外的带宽和资源消耗。因此,在实际应用中,需要权衡利弊并根据具体情况决定是否使用懒加载和预加载。</p> </blockquote> <p><strong>8.浏览器的存储方法有那些?</strong></p> <blockquote> <p>在Web开发中,有多种方法可以在浏览器中存储数据,以便在不同页面之间或在不同浏览器会话之间共享数据。以下是一些常见的浏览器存储方法:</p> <ol><li> <p><strong>Cookies(Cookie)</strong>:</p> Cookies是最早的浏览器存储方法之一,它们是小型文本文件,存储在用户计算机上。Cookies通常用于存储少量数据,如会话标识、用户偏好设置等。它们可以通过JavaScript访问和操作。</li><li> <p><strong>Web Storage(本地存储)</strong>:</p> Web Storage包括LocalStorage和SessionStorage两种类型。它们是浏览器提供的键值对存储机制,用于存储大量数据。LocalStorage存储的数据在浏览器关闭后仍然可用,而SessionStorage只在当前会话期间可用。</li><li> <p><strong>IndexedDB</strong>:</p> IndexedDB是一种高级的浏览器存储API,用于存储结构化数据。它提供了强大的查询和索引功能,允许存储大量数据,并支持事务处理。IndexedDB通常用于离线应用程序和大规模数据存储。</li><li> <p><strong>Cookies with HttpOnly</strong>:</p> 除了标准的Cookies,还可以使用具有HttpOnly标志的Cookies来存储敏感数据,这些Cookies不能通过JavaScript访问,从而增强了安全性。它们通常用于存储会话令牌等敏感信息。</li><li> <p><strong>WebSQL(已弃用)</strong>:</p> WebSQL是一种关系型数据库,已经被废弃,不建议在新项目中使用。它允许通过SQL查询存储和检索数据。</li><li> <p><strong>Cache Storage</strong>:</p> Cache Storage是浏览器的缓存机制,用于存储静态资源,如CSS、JavaScript文件、图像等,以提高网页加载速度。Service Workers可以用于更高级的缓存控制。</li><li> <p><strong>Session Cookies</strong>:</p> Session Cookies是一种特殊的Cookies,它们在浏览器会话结束后自动删除。它们通常用于存储临时数据,如购物车内容或临时会话信息。</li><li> <p><strong>LocalStorage with Expiration</strong>:</p> 通过结合LocalStorage和JavaScript的定时器,可以实现带有过期时间的本地存储。这允许在一段时间后自动删除存储的数据。</li></ol> <p>选择适当的浏览器存储方法取决于你的应用程序需求和数据类型。Cookies适用于小型文本数据,而Web Storage适用于较大的键值对数据。IndexedDB适用于大规模数据存储,而Cache Storage用于缓存静态资源。安全性也是考虑因素之一,某些存储方法更适合存储敏感信息。最终,根据你的具体用例选择合适的浏览器存储方法是最重要的。</p> </blockquote> <p><strong>9.解释浏览器缓存以及它的好处。</strong></p> <blockquote> <p>浏览器缓存是一种用于存储Web页面和资源的机制,以便在将来访问同一页面或资源时,可以更快地获取它们。浏览器缓存将一些页面内容、图像、样式表、脚本和其他资源保存在用户的本地存储中,以减少从远程服务器重新下载这些资源的需求。以下是浏览器缓存的一些好处:</p> <p><strong>1. 提高加载速度:</strong></p> <ul><li>最明显的好处是提高页面加载速度。当用户首次访问网站时,浏览器会下载并缓存页面的各种资源(如HTML、CSS、JavaScript、图像等)。在用户再次访问相同页面时,浏览器可以直接从缓存中获取这些资源,而不必再次从服务器下载,从而减少了加载时间。</li></ul> <p><strong>2. 减少服务器负载:</strong></p> <ul><li>由于浏览器缓存减少了对服务器的请求,因此可以减轻服务器的负载。这对于高流量的网站来说尤为重要,因为它可以帮助减少服务器的响应时间和带宽成本。</li></ul> <p><strong>3. 减少网络流量:</strong></p> <ul><li>缓存还有助于减少网络流量。用户不需要每次都下载相同的资源,这可以减少移动设备用户的数据消耗,并减轻拥挤的网络环境下的负担。</li></ul> <p><strong>4. 提高用户体验:</strong></p> <ul><li>快速加载的页面和资源可以提高用户体验。用户更愿意留在加载快速的网站,而不会因长时间的加载而感到沮丧。</li></ul> <p><strong>5. 离线访问:</strong></p> <ul><li>浏览器缓存还支持离线访问。一些Web应用程序和内容可以被完全缓存,以便用户在没有互联网连接的情况下仍然可以访问它们。</li></ul> <p><strong>6. 节省带宽:</strong></p> <ul><li>对于移动设备用户和那些有限带宽的用户来说,浏览器缓存可以显著节省带宽成本,因为它减少了从服务器下载资源的需求。</li></ul> <p>虽然浏览器缓存提供了许多好处,但在开发过程中需要小心处理。开发者需要确保在更新网站或应用程序时,已经更改的资源能够正确地被客户端缓存更新,以避免用户看到过时的内容。为此,可以使用版本控制或添加缓存清除机制。总的来说,浏览器缓存是Web性能优化的关键工具,可以提高网站的速度和用户体验。</p> </blockquote> <p><strong>10.在输入URL后,浏览器发生了什么?</strong></p> <blockquote> <p>当您在浏览器中输入URL并按下回车键时,浏览器会执行一系列步骤来加载和显示网页。以下是浏览器在输入URL后的典型行为:</p> <ol><li> <p><strong>URL解析:</strong> 浏览器首先解析您输入的URL。URL通常包括协议(如HTTP或HTTPS)、主机名(域名)、端口号(如果未明确指定,默认为80或443)、路径(指定要请求的资源路径)、查询参数和片段标识符等部分。</p> </li><li> <p><strong>DNS解析:</strong> 浏览器需要将主机名解析为IP地址,以便确定要连接到的服务器的位置。它会查询本地DNS缓存,如果找不到,则会向DNS服务器发送请求,获取IP地址。</p> </li><li> <p><strong>建立TCP连接:</strong> 浏览器使用解析得到的IP地址和端口号,通过TCP/IP协议与服务器建立连接。这个过程包括TCP的三次握手。</p> </li><li> <p><strong>发起HTTP请求:</strong> 浏览器根据URL和其他请求头信息(如User-Agent、Accept等)构建一个HTTP请求,并发送给服务器。请求可能是GET请求(用于获取资源)、POST请求(用于提交表单数据)或其他HTTP方法。</p> </li><li> <p><strong>服务器处理请求:</strong> 服务器接收到HTTP请求后,会根据请求的内容和服务器上的配置来处理请求。这可能包括查询数据库、生成动态内容、读取文件等操作。</p> </li><li> <p><strong>服务器响应:</strong> 服务器会生成一个HTTP响应,其中包括状态码(表示请求成功、失败或其他情况)、响应头(包括响应的MIME类型、内容长度等信息)以及响应体(实际的HTML、CSS、JavaScript或其他资源内容)。</p> </li><li> <p><strong>接收和渲染内容:</strong> 浏览器接收到服务器的响应后,会根据响应头中的MIME类型确定如何处理内容。如果是HTML页面,浏览器会解析HTML、加载CSS和JavaScript,构建DOM树和渲染树,最终将页面显示在屏幕上。</p> </li><li> <p><strong>资源加载:</strong> 页面中可能包含其他资源,如图片、样式表、脚本文件等。浏览器会根据HTML内容中的链接和标签,发起额外的HTTP请求来获取这些资源。</p> </li><li> <p><strong>执行JavaScript:</strong> 如果页面包含JavaScript代码,浏览器会执行这些代码,从而使页面具有交互性和动态性。</p> </li><li> <p><strong>用户交互:</strong> 用户可以与页面交互,单击链接、填写表单、滚动页面等。</p> </li><li> <p><strong>异步请求:</strong> 页面中的JavaScript代码可以发起异步请求,与服务器交互以获取或提交数据。这些请求通常使用XMLHttpRequest对象或Fetch API。</p> </li><li> <p><strong>页面更新:</strong> 页面可能会根据用户交互或异步请求的响应进行更新,以反映最新的数据或状态。</p> </li><li> <p><strong>浏览历史记录:</strong> 浏览器会跟踪用户的浏览历史,以便用户可以通过后退、前进等操作导航到不同的页面。</p> </li><li> <p><strong>安全性:</strong> 浏览器会执行一系列安全性检查,包括跨站脚本(XSS)和跨站请求伪造(CSRF)等,以保护用户免受潜在的安全威胁。</p> </li><li> <p><strong>页面加载完成:</strong> 当所有资源都加载完成并且页面准备就绪时,浏览器触发<code>DOMContentLoaded</code>事件,表示页面可以与用户进行互动。</p> </li><li> <p><strong>关闭连接:</strong> 当页面加载完成后,浏览器会维护与服务器的TCP连接一段时间,以便更快地获取后续资源。最终,这些连接会被关闭。</p> </li></ol> <p>这些步骤涵盖了浏览器在输入URL后的主要行为,其中包括了网络请求、资源加载、页面渲染和用户交互等关键过程。这些过程使得浏览器能够将Web内容呈现给用户,并提供了丰富的互联网体验。</p> </blockquote> <p></p> <h2><a name="t6"></a>七.Node篇 </h2> <p><strong>1.Node.js是什么?它与JavaScript有什么关系?</strong></p> <blockquote> <p>Node.js是一个基于Chrome V8 JavaScript引擎的服务器端运行时环境,用于构建高性能的网络应用程序。它允许开发者使用JavaScript语言来编写服务器端应用程序,而不仅仅局限于浏览器中的客户端脚本。</p> <p>以下是Node.js与JavaScript之间的关系和一些关键特点:</p> <ol><li> <p><strong>JavaScript语言:</strong> Node.js使用JavaScript作为主要的编程语言。JavaScript是一种脚本语言,最初设计用于在网页上执行客户端脚本,但Node.js扩展了其应用范围,使其可以用于服务器端编程。</p> </li><li> <p><strong>运行环境:</strong> Node.js提供了一个独立的运行时环境,包括一个事件驱动的非阻塞I/O系统,使其能够高效地处理并发请求。这与浏览器中的JavaScript执行环境有所不同,后者通常是单线程的。</p> </li><li> <p><strong>跨平台:</strong> Node.js可在多个操作系统上运行,包括Windows、macOS和各种Linux发行版。这使得开发者可以使用相同的代码在不同的平台上构建应用程序。</p> </li><li> <p><strong>模块系统:</strong> Node.js拥有自己的模块系统,允许开发者将代码组织成模块并使用<code>require</code>和<code>module.exports</code>来导入和导出模块,以便在应用程序中重用代码。</p> </li><li> <p><strong>生态系统:</strong> Node.js拥有庞大的包生态系统,通过npm(Node Package Manager)提供了数以千计的可用包,这些包可以轻松地集成到Node.js应用程序中,加速开发过程。</p> </li><li> <p><strong>非阻塞和事件驱动:</strong> Node.js使用非阻塞I/O和事件驱动的编程模型,允许应用程序同时处理多个请求而不会阻塞主线程,从而实现高性能和可伸缩性。</p> </li><li> <p><strong>适用领域:</strong> Node.js广泛应用于构建Web服务器、API服务器、实时通信应用(如聊天应用和在线游戏)、物联网(IoT)设备控制、后端微服务和各种网络应用程序。</p> </li></ol> <p>总之,Node.js是一个强大的服务器端运行时环境,它允许开发者使用JavaScript语言构建高性能、可伸缩的网络应用程序。它与浏览器中的JavaScript密切相关,但它们的执行环境和用途有所不同。</p> </blockquote> <p><strong>2.Node.js中的事件循环是什么?它的作用是什么? </strong></p> <blockquote> <p>Node.js中的事件循环(Event Loop)是其核心机制之一,它用于管理异步操作和事件驱动的非阻塞I/O。事件循环是Node.js的基础,它使Node.js能够高效地处理并发请求而不阻塞主线程,从而实现高性能和可伸缩性。以下是关于Node.js事件循环的详细解释:</p> <ol><li> <p><strong>什么是事件循环:</strong> 事件循环是一个长时间运行的进程或线程,负责处理事件和任务。在Node.js中,事件循环是一个单线程的执行环境,用于处理异步操作、回调函数和事件触发。</p> </li><li> <p><strong>工作原理:</strong> 事件循环不断地监听事件队列,当事件到达时,它会执行与事件相关联的回调函数。这使得Node.js能够同时处理多个任务而不会阻塞主线程。事件循环遵循一个特定的执行顺序,通常包括以下阶段:</p> <ul><li><strong>Timers 阶段:</strong> 处理<code>setTimeout()</code>和<code>setInterval()</code>等计时器的回调函数。</li><li><strong>I/O Callbacks 阶段:</strong> 处理已完成的I/O操作的回调函数。</li><li><strong>Idle, Prepare 阶段:</strong> 用于内部处理。</li><li><strong>Poll 阶段:</strong> 负责轮询I/O事件队列,等待新的事件到达。</li><li><strong>Check 阶段:</strong> 处理<code>setImmediate()</code>的回调函数。</li><li><strong>Close Callbacks 阶段:</strong> 处理关闭事件(例如<code>socket.on('close', ...)</code>的回调函数)。</li></ul></li><li> <p><strong>作用:</strong> 事件循环的主要作用是实现非阻塞的异步编程。它允许Node.js在等待I/O操作完成时,继续执行其他任务,而不必等待阻塞操作的完成。这提高了Node.js的性能和响应性,使其适用于高并发的应用场景,如Web服务器和实时通信应用。</p> </li><li> <p><strong>事件驱动编程:</strong> Node.js采用事件驱动的编程模型,开发者可以绑定事件处理程序(回调函数)到特定的事件,当事件发生时,相关的回调函数将被触发执行。这种模型使得编写异步代码更加容易和直观。</p> </li><li> <p><strong>回调函数:</strong> 大多数Node.js操作都接受回调函数作为参数,这些回调函数在操作完成时被调用。回调函数通常在事件循环的适当阶段执行,以确保异步操作的正确执行。</p> </li></ol> <p>总之,Node.js中的事件循环是一种强大的机制,使得异步编程变得容易且高效。它允许Node.js在等待I/O操作完成时执行其他任务,以提供出色的性能和可伸缩性,适用于构建高性能的网络应用程序。同时,事件循环也是Node.js事件驱动编程模型的核心组成部分。</p> </blockquote> </div> </div> </li> <li class="list-group-item ul-li"> <b>相关阅读:</b><br> <nobr> <a href="/Article/Index/951775">Thrift/RPC学习分享</a> <br /> <a href="/Article/Index/1222521">组合数学笔记-特殊计数数列</a> <br /> <a href="/Article/Index/1560888">✪✪✪宁波国家实验室认可✪✪✪</a> <br /> <a href="/Article/Index/711620">白杨SEO对话老姜:聊聊第三方平台站内SEO,第三方平台的引流的逻辑是什么?</a> <br /> <a href="/Article/Index/1206492">Ubuntu 20.04 系统最快安装WRF软件手册</a> <br /> <a href="/Article/Index/710726">Spring注解</a> <br /> <a href="/Article/Index/1724847">对抗生成网络GANP52-</a> <br /> <a href="/Article/Index/1009269">Unity中的动画系统</a> <br /> <a href="/Article/Index/1341903">JavaEE-线程进阶</a> <br /> <a href="/Article/Index/1710405">vector的特性及使用</a> <br /> </nobr> </li> <li class="list-group-item from-a mb-2"> 原文地址:https://blog.csdn.net/m0_71469120/article/details/132924949 </li> </ul> </div> <div class="col-lg-4 col-sm-12"> <ul class="list-group" style="word-break:break-all;"> <li class="list-group-item ul-li-bg" aria-current="true"> 最新文章 </li> <li class="list-group-item ul-li"> <nobr> <a href="/Article/Index/1484446">攻防演习之三天拿下官网站群</a> <br /> <a href="/Article/Index/1515268">数据安全治理学习——前期安全规划和安全管理体系建设</a> <br /> <a href="/Article/Index/1759065">企业安全 | 企业内一次钓鱼演练准备过程</a> <br /> <a href="/Article/Index/1485036">内网渗透测试 | Kerberos协议及其部分攻击手法</a> <br /> <a href="/Article/Index/1877332">0day的产生 | 不懂代码的"代码审计"</a> <br /> <a href="/Article/Index/1887576">安装scrcpy-client模块av模块异常,环境问题解决方案</a> <br /> <a href="/Article/Index/1887578">leetcode hot100【LeetCode 279. 完全平方数】java实现</a> <br /> <a href="/Article/Index/1887512">OpenWrt下安装Mosquitto</a> <br /> <a href="/Article/Index/1887520">AnatoMask论文汇总</a> <br /> <a href="/Article/Index/1887496">【AI日记】24.11.01 LangChain、openai api和github copilot</a> <br /> </nobr> </li> </ul> <ul class="list-group pt-2" style="word-break:break-all;"> <li class="list-group-item ul-li-bg" aria-current="true"> 热门文章 </li> <li class="list-group-item ul-li"> <nobr> <a href="/Article/Index/888177">十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!</a> <br /> <a href="/Article/Index/797680">奉劝各位学弟学妹们,该打造你的技术影响力了!</a> <br /> <a href="/Article/Index/888183">五年了,我在 CSDN 的两个一百万。</a> <br /> <a href="/Article/Index/888179">Java俄罗斯方块,老程序员花了一个周末,连接中学年代!</a> <br /> <a href="/Article/Index/797730">面试官都震惊,你这网络基础可以啊!</a> <br /> <a href="/Article/Index/797725">你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法</a> <br /> <a href="/Article/Index/797702">心情不好的时候,用 Python 画棵樱花树送给自己吧</a> <br /> <a href="/Article/Index/797709">通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!</a> <br /> <a href="/Article/Index/797716">13 万字 C 语言从入门到精通保姆级教程2021 年版</a> <br /> <a href="/Article/Index/888192">10行代码集2000张美女图,Python爬虫120例,再上征途</a> <br /> </nobr> </li> </ul> </div> </div> </div> <!-- 主体 --> <!--body结束--> <!--这里是footer模板--> <!--footer--> <nav class="navbar navbar-inverse navbar-fixed-bottom"> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="text-muted center foot-height"> Copyright © 2022 侵权请联系<a href="mailto:2656653265@qq.com">2656653265@qq.com</a>    <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2022015340号-1</a> </div> <div style="width:300px;margin:0 auto; padding:0px 5px;"> <a href="/regex.html">正则表达式工具</a> <a href="/cron.html">cron表达式工具</a> <a href="/pwdcreator.html">密码生成工具</a> </div> <div style="width:300px;margin:0 auto; padding:5px 0;"> <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502049817" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;"> <img src="" style="float:left;" /><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">京公网安备 11010502049817号</p></a> </div> </div> </div> </div> </nav> <!--footer--> <!--footer模板结束--> <script src="/js/plugins/jquery/jquery.js"></script> <script src="/js/bootstrap.min.js"></script> <!--这里是scripts模板--> <!--scripts模板结束--> </body> </html>