0


【面试宝典】2023前端面试题

文章目录

一、HTML

1、简述一下对HTML语义化的理解?

用正确的标签做正确的事情。
HTML语义化让页面的内容结构化,结构更清晰,便于浏览器、搜索引擎解析;即使在没有css样式的情况下,也以一种文档格式显示,并且是容易阅读的
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于seo优化
使阅读源代码的人更容易将网站分块,便于阅读维护理解

2、标签上 title 与 alt 属性的区别是什么?

通常当鼠标滑动到元素上的时候显示
alt 是img标签 的特有属性,是图片内容的等价描述,
用于图片无法加载显示、读屏器阅读图片。可提图片高可访问性,
除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。

3、href 与 src?

  • href (Hypertext Reference)指定网络资源的位置,从而在当前元素或者当前文档和由当前属性定义的需要的锚点或资源之间定义一个链接或者关系。(目的不是为了引用资源,而是为了建立联系,让当前标签能够链接到目标地址。)
  • src source(缩写),指向外部资源的位置,指向的内容将会应用到文档中当前标签所在位置。
  • href与src的区别:
  • 1、请求资源类型不同:href 指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的联系。在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片;
  • 2、作用结果不同:href 用于在当前文档和引用资源之间确立联系;src 用于替换当前内容;
  • 3、浏览器解析方式不同:当浏览器解析到src ,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等也如此,类似于将所指向资源应用到当前内容。这也是为什么建议把 js 脚本放在底部而不是头部的原因。

4、HTML新特性?

新增用于绘画的 canvas 和 svg 元素
新增 video(视频) 和 audio(音频) 标签
新增客户端数据存储新方法:sessionStorage、localStorage
新增多个语义化标签元素:
·header、nav、article、section、aside、footer
表单的增强应用:
·表单元素 input 的 type 属性扩充:
·date、time、email、url、search、range、month、color、number ·表单元素 input 通过属性进行表单验证:
·required(必填项)、pattern(正则表达式验证表单输入)
新增地理定位 - Geolocation API 用于获得用户的地理位置

5、Localstorage、SessionStorage、cookie区别

1、cookie
(1)本身用于客户端和服务端通信
(2)但是它有本地存储的功能,于是就被“借用”
(3)document.cookie = …获取和修改即可
(4)cookie用于存储的缺点
①存储量太小,只有4kb
②所有http请求都带着,会影响获取资源的效率
③api简单,需要封装才能用document.cookie

2、localStorage,sesseionStorage
(1)html5专门为存储而设计,最大容量5M
(2)api简单易用
(3)lcoalStorage.setItem(key, value);localStorage.getItem(key);
(4)ios safari隐藏模式下:localStorage.getItem会报错,建议统一使用try-catch封装

3、sessionStorage用于本地存储一个会话(session)中的数据,
这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。
因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。
而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

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

相似存储

localStorage 长期存储数据,浏览器关闭后数据不丢失; sessionStorage 数据在浏览器关闭后自动删除。

离线的存储

两种方式

HTML5 的离线存储.appcache文件【废弃】
service-worker 的标准
HTML5 的离线存储.appcache文件【废弃】

在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。

原理:HTML5 的离线存储是基于一个新建的。appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像 cookie 一样被存储了下来。

之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。

如何使用

1、页面头部像下面一样加入一个 manifest 的属性
2、在 cache.manifest 文件的编写离线存储的资源

CACHE MANIFEST
#v0.11
CACHE:
js/app.js
css/style.css
NETWORK:
resourse/logo.png
FALLBACK:
/ /offline.html
 

3、在离线状态时,操作 window.applicationCache 进行需求实现。

service-worker

可以参考

http://www.alloyteam.com/2019/07/web-applications-offline/
https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
————————————————
版权声明:本文为CSDN博主「孙叫兽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41937552/article/details/111591669

7、常见的浏览器内核

**Trident内核:**代表浏览器是ie浏览器,因此Trident内核又称E内核,
  此内核只能用于Windows平台,并且不是开源的。

**Gecko内核:**代表浏览器是Firefox浏览器。Gecko内核是开源的,
  最大优势是可以跨平台。

**Webkit内核:代表浏览器是Safari(苹果的浏览器)以及低版本的谷歌浏览器,
  是开源的项目。

**Presto内核:**代表浏览器是Opera浏览器(中文译为“欧朋浏览器”),
  Presto内核是世界公认最快的渲染速度的引擎,但是在2013年之后,
  Open宣布加入谷歌阵营,弃用了该内核。

**Blink内核:**由谷歌和Opera开发,2013年4月发布,现在Chrome内核是Blink。

8、你对web标准以及W3C的理解?

web标准:

    web标准主要分为结构、表现、行为3部分

    结构:指我们平时在body里面写的标签,主要是由HTML标签组成

    表现:指更加丰富HTML标签样式,主要由CSS样式组成

    行为:指页面和用户的交互,主要由JS部分组成
W3C:

W3C对web标准提出了规范化的要求,即代码规范

对结构的要求

1、标签字母要小写

2、标签要闭合

3、标签不允许随意嵌套
对表现和行为的要求

1、建议使用外链CSS和js脚本,实现结构与表现分离、结构与行为分离,
能提高页面的渲染效率,更快地显示网页内容

9、行内元素和块级元素有哪些?img属于什么元素

特点:
块级元素:独占一行;可设置宽高;margin 和 padding 均有效;
行内元素:不独占一行,可在一行显示;设置宽高无效;margin 上下无效、左右有效;padding 均有效;
行内块元素:不独占一行,可在一行显示;可以设置宽高;margin 和 padding 均有效;
转换:
转为块元素:display: block;
转为行内元素: display: inline;
转为行内块元素:display: inline-block;

10、表单中readonly和disabled的区别?

共同点:能够使用户不能改变表单中的内容

不同点:
1、readonly只对input和textarea有效,但是disabled对所有的表单元素都是有效的,
包括radio、checkbox
2、readonly可以获取到焦点,只是不能修改。
disabled设置的文本框无法获取焦点
3、如果表单的字段是disabled,则该字段不会发送(表单传值)和序列化

11、如何进行网站性能优化?

content 方面
减少 HTTP 请求:合并文件、CSS 精灵、inline Image
减少 DNS 查询:DNS 缓存、将资源分布到恰当数量的主机名
减少 DOM 元素数量
Server 方面
使用 CDN
配置 Etag
对组件使用 Gzip 压缩
Cookie 方面
减少cookie大小
css 方面
将样式表放到页面顶部
不使用 CSS 表达式
使用 <link> 不使用 @import
Javascript 方面
将脚本放到页面底部
将 javascript 和 css 从外部引入
压缩 javascript 和 css
删除不需要的脚本
减少 DOM 访问
图片方面
优化图片:根据实际颜色需要选择色深、压缩
优化 css 精灵
不要在 HTML 中拉伸图片

12、如何写出高性能的 HTML?

避免使用 Iframe

Iframe 也叫内联 frame,可以把一个 HTML 文档嵌入到另一个文档中。使用 iframe 的好处是被嵌入的文档可以完全独立于其父文档,
凭借此特点我们通常可以使浏览器模拟多线程,需要注意的是使用 iframe 并不会增加同域名下的并行下载数,
浏览器对同域名的连接总是共享浏览器级别的连接池,即使是跨窗口或跨标签页,这在所有主流浏览器都是如此。
也因为这样这让 iframe 带来的好处大打折扣。

在页面加载过程中 iframe 元素会阻塞父文档 onload 事件的触发,而开发者程序通常会在 onload 事件触发时初始化 UI 操作。
例如,设置登录区域的焦点。因为用户习惯等待这一操作,所以尽可能的让 onload 事件触发从而使用户的等待时间变短是非常重要的。
另外开发者会把一些重要的行为绑定在 unload 事件上,而不幸的是在一些浏览器中,只有当 onload 事件触发后 unload 事件才能触发,
如果 onload 事件长时间未触发,而用户已经离开当前页面,那么 unload 事件也将永远得不到触发。
 那是否有方案可以让 onload 事件不被 iframe 阻塞吗?有个简单的解决方案来避免 onload 事件被阻塞,
 使用 JavaScript 动态的加载 iframe 元素或动态设置 iframe 的 src 属性:

<iframeid=iframe1></iframe>
document.getElementById(‘iframe1’).setAttribute(‘src’, ‘url’);
但其仅在高级浏览器 中有效,对于 Internet Explorer 8 及以下的浏览器无效。
除此之外我们必须知道 iframe 是文档内最消耗资源的元素之一,在 Steve Souders 的测试中 ,在测试页面中分别加载 100 个 A、DIV、
SCRIPT、STYLE 和 IFRAME 元素,并且分别在 Chrome、Firefox、Internet Explorer、Opera、Safari 中运行了 10 次。
结果显示创建 iframe 元素的开销比创建其他类型的 DOM 元素要高 1~2 个数量级。在测试中所有的 DOM 元素都是空的,
如加载大的脚本或样式块可能比加载某些 iframe 元素耗时更长,但从基准测试结果来看,即使是空的 iframe,其开销也是非常昂贵的,
鉴于 iframe 的高开销,我们应尽量避免使用。尤其是对于移动设备,对于目前大部分还是只有有限的 CPU 与内存的情况下,
更应避免使用 iframe。

避免空链接属性

空的链接属性是指 img、link、script、ifrrame 元素的 src 或 href 属性被设置了,但是属性却为空。如<imgsrc=''>,
我们创建了一个图片,并且暂时设置图片的地址为空,希望在未来动态的去修改它。但是即使图片的地址为空,
浏览器依旧会以默认的规则去请求空地址:

Internet Explorer 8 及以下版本浏览器只在 img 类型元素上出现问题,IE 会把 img 的空地址解析为当前页面地址的目录地址。
例如:如果当前页面地址为 http://example.com/dir/page.html,IE 会把空地址解析为 http://example.com/dir/ 地址并请求。
早些版本的 Webkit 内核浏览器 与 Firefox 会把空地址解析为当前页面的地址。如果页面内有多个空链接属性元素,
当前页面的服务器则会被请求多次,增加服务器的负载。相较桌面浏览器对内核的更新升级较积极,
这个问题在 ios 与 android 系统的移动浏览器上问题可能较严重。幸运的是所有主流浏览器面对 iframe 的 src 属性为空时,
会把空地址解析为 about:blank 地址,而不会向服务器发出额外的请求。

避免节点深层级嵌套

深层级嵌套的节点在初始化构建时往往需要更多的内存占用,并且在遍历节点时也会更慢些,这与浏览器构建 DOM 文档的机制有关。
例如下面 HTML 代码:

<html><body><p>
Hello World
</p><div><imgsrc="example.png"/></div></body></html>
通过浏览器 HTML 解析器的解析,浏览器会把整个 HTML 文档的结构存储为 DOM 树结构。
当文档节点的嵌套层次越深,构建的 DOM 树层次也会越深。

缩减 HTML 文档大小

提高下载速度最显而易见的方式就是减少文件的大小,特别是压缩内嵌在 HTML 文档中的 JavaScript 和 CSS 代码,
这能使得页面体积大幅精简。除此之外减少 HTML 文档大小还可以采取下面几种方法:

删掉 HTM 文档对执行结果无影响的空格空行和注释
避免 Table 布局
使用 HTML5
显式指定文档字符集

HTML 页面开始时指定字符集,有助于浏览器可以立即开始解析 HTML 代码。HTML 文档通常被解析为一序列的带字符集编码信息的字符串
通过 internet 传送。字符集编码在 HTTP 响应头中,或者 HTML 标记中指定。浏览器根据获得的字符集,
把编码解析为可以显示在屏幕上的字符。如果浏览器不能获知页面的编码字符集,一般都会在执行脚本和渲染页面前,把字节流缓存,
然后再搜索可进行解析的字符集,或以默认的字符集来解析页面代码,这会导致消耗不必要的时间。
为了避免浏览器把时间花费在搜寻合适的字符集来进行解码,所以最好在文档中总是显式的指定页面字符集。

显式设置图片的宽高

当浏览器加载页面的 HTML 代码时,有时候需要在图片下载完成前就对页面布局进行定位。

如果 HTML 里的图片没有指定尺寸(宽和高),或者代码描述的尺寸与实际图片的尺寸不符时,
浏览器则要在图片下载完成后再 “回溯” 该图片并重新显示,这会消耗额外时间。

所以,最好为页面里的每一张图片都指定尺寸,不管是在页面 HTML 里的<img> 标签,还是在 CSS 里。

<imgsrc="hello.png"width="400"height="300">
避免脚本阻塞加载

当浏览器在解析常规的 script 标签时,它需要等待 script 下载完毕,再解析执行,而后续的 HTML 代码只能等待。
为了避免阻塞加载,应把脚步放到文档的末尾,如把 script 标签插入在 body 结束标签之前:

<scriptsrc="example.js"></script>

————————————————
版权声明:本文为CSDN博主「孙叫兽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41937552/article/details/111591669

13、iframe 的优缺点?

优点:

  • 解决加载缓慢的第三方内容如图标和广告等的加载问题
  • Security sandbox
  • 并行加载脚本
  • 缺点:
  • iframe会阻塞主页面的Onload事件
  • 即时内容为空,加载也需要时间
  • 没有语意

二、CSS

1、css3新特性?

颜色:新增 RGBA,HSLA 模式,新增透明度
盒子阴影:(box-shadow)
边框:
边框圆角:(border-radius)
边框阴影:(box-shadow)
边框图片:(border-image)
弹性盒子模型:(box-sizing:border-box;)
背景:
background-size :设置背景图片的尺寸
background-origin :设置背景图片的原点(定位、位置)
background-clip :设置背景图片的裁切区域,以”,”分隔,可以设置多背
景,用于自适应布局。
渐变:
linear-gradient:(线性渐变)
radial-gradient :(径向渐变)
新增过渡效果:
transition,配合动态伪类使用
自定义动画:
animation 定义动画:@keyframes 动画名称
媒体查询@media,多栏布局: @media screen and (width:500px) {

}
2D 转换:
transform:translate(x,y) 移动
rotate(x,y) 旋转
skew(x,y) 翻转
scale(x,y) 缩放
3D 转换
字体图标 : font-face
弹性布局 :flex
新增多种选择器(结构伪类选择器、动态伪类选择器、属性选择器等)

2、什么是盒子模型

盒模型分为两类:标准盒模型和怪异盒模型(IE 盒模型)
盒模型的组成部分(由外向内):
margin(外边距)+ border(边框)+ padding(内边距)+ content(盒子内容大小)
注:
标准盒模型的 width 指的是内容 content 的宽度,height 指的是 content 的高度
怪异盒模型的 width 指的是内容、边框、内边距总的宽度(content + border + padding);
height 指的是内容、边框、内边距总的高度
盒子转换方式:
如果 doctype 协议缺失,会由浏览器自己界定。
在 IE 浏览器中 IE9 以下(IE6、IE7、IE8)的版本触发怪异模式,其他浏览器中会默认
为 W3C 标准模式。
box-sizing: content-box 标准盒模型
box-sizing: border-box IE 盒模型

3、CSS选择器以及优先级的理解?

常用的CSS选择器

    ID选择器、类选择器、标签选择器、属性选择器、伪类选择器、后代选择器

权重划分

  在同一层级下:

  !important > 内联样式 > ID选择器 > 类选择器 > (标签选择器、伪类选择器、属性选择器)

不同层级下:

    正常来说权重值越高的优先级越高,但是一直以来没有具体的权重值划分,
    所以目前大多数开发中层级越深的优先级越高

4、谈谈你对回流和重绘的理解?

什么是回流?

当一个元素自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化
,导致需要重新构建页面的时候,就产生了回流复制

什么是重绘?

当一个元素自身的宽高,布局,及显示或隐藏没有改变,
而只是改变了元素的外观风格的时候,就产生了重绘

什么时候会进行回流?

添加或者删除可见的 DOM 元素的时候
元素的位置发生改变
元素的尺寸发生改变
内容改变
页面第一次渲染的时候

什么时候会进行重绘?

列举一些相关的 CSS 样式:color、background、
background-size、visibility、box-shadow

5、实现元素隐藏的方式

opacity:0; /* 设置透明度为 0 */
display:none; /* 设置透明度为 0 */
visibility:hidden; /* 设置透明度为 0 */
transform:scale(0) /* CSS3 的新特性,让元素缩小至 0 */
z-index:-9999; /* 设置元素的层级,需给元素设置定位 position : absolute; */

6、css 预处理器

less
sass

7、垂直居中几种方式?

单行文本: line-height = height
图片: vertical-align: middle;
盒子:1. 定位(子绝父相)实现垂直居中
父元素:相对定位;
子元素:绝对定位;
top:calc(50% - 子元素自身的一半) /子元素需具备高度/
left:calc(50% - 子元素自身的一半) /子元素需具备宽度/
2. 定位+transform: translate(-50%, -50%)(常用)
3. fixed 定位居中
4. flex 弹性布局居中(常用)
给父盒子设置 display:flex; justify-content:center; align-items:center;

8、简明说一下 CSS link 与 @import 的区别和用法?

link 是 XHTML 标签,除了加载CSS外,还可以定义 RSS 等其他事务;@import 属于 CSS 范畴,只能加载 CSS。
link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。
link 是 XHTML 标签,无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
link 支持使用 Javascript 控制 DOM 去改变样式;而@import不支持。

9、display:none和visibility:hidden的区别?

display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。

10、rgba和opacity的透明效果有什么不同?

opacity 会继承父元素的 opacity 属性,而 RGBA 设置的元素的后代元素不会继承不透明属性。

11、行内元素与块级元素有什么区别?

① 排列方式:
行内元素间会在同一行进行排列(水平方向);
块级元素独占一行,垂直向下排列(垂直方向)
②宽高和内外边距:
行内元素设置宽高无效,宽高随文本内容的变化而变化,但可以设置行高;
行内元素设置内外边距(margin 和 padding)上下无效,左右有效;
③元素嵌套:
块级元素可以包含行内元素和块级元素,还可以容纳内联元素和其他元素;
行内元素不能包含块级元素,只能容纳文本或者其他行内元素

12、清除浮动的方式

1 给浮动元素的父元素添加高度(不推荐)
2 给父盒子添加 overflow:hidden;来清除浮动(不推荐)
3 空标签法:给父盒子内部的最后面添加一个空标签(必须为块级标签),并给空标
签设置 clear:both;(不推荐)
4.双伪元素清除浮动(推荐):
.clearfix::before,.clearfix::after {
content: ’’;
clear: both;
display: block;
height: 0;
visibility: hidden;
zoom: 1;//兼容IE6
}

13、引入样式表CSS的方式有几种?分别是什么?优先级是什么?

在HTML中常用以下四种方式定义CSS

inline(内联式,也称行内样式)、
embedding(嵌入式)、
linking(外部引用式)
导入样式表(@import )。

详细
一:内联式/行内样式:使用该属性可以直接指定样式,当然,该样式仅能用于该元素的内容,对于另一个同名的元素则不起作用。
二:嵌入式(style):用户可在HTML文档头部定义多个style元素,实现多个样式表。
三:外部引用式(link)

①可以在多个文档间共享样式表,对于较大规模的网站,将CSS样式定义独立成一个一个的文档,可有效地提高效率,并有利于对网站风格的维护。
②可以改变样式表,而无需更改HTML文档,这也与HTML语言内容与形式分开的原则相一致。
③可以根据介质有选择的加载样式表。
四:导入样式表:@import url(“css/base.css”);

优先级:就近原则

内联式>内嵌式>外部引用式>导入样式表

13、如何实现浏览器响应式布局?

常用如下
    使用媒体查询(@media)
    使用flex弹性布局
    使用百分比单位
    使用rem单位
    使用VH、HW单位

推荐一种冷门万能自适应方式:tranfrom:scale(动态比值)

三、JS

1、JS数据类型

基本数据类型
Number、String、Boolean、Null、Undefined、Symbol、bigInt
引用数据类型
object、Array、Date、Function、RegExp

2、如何判断js的数据类型

判断方法
typeof
typeof 可以用来区分除了 Null 类型以外的原始数据类型,对象类型的可以从普通对象里面
识别出函数:

typeof undefined // "undefined"
typeof null // "object"
typeof 1 // "number"
typeof "1" // "string"
typeof Symbol() // "symbol"
typeof function() {} // "function"
typeof {} // "object"

问题一:typeof 不能识别 null,如何识别 null?
答案:如果想要判断是否为 null,可以直接使用===全等运算符来判断(或者使用下面的
Object.prototype.toString 方法):

let a = null
a === null // true

问题二:typeof 作用于未定义的变量,会报错吗?
答案:不会报错,返回"undefined"。

typeof randomVariable // "undefined" 

问题三:typeof Number(1)的返回值是什么?
答案:“number”。注意 Number 和 String 作为普通函数调用的时候,是把参数转化为相 应
的原始数据类型,也就是类似于做一个强制类型转换的操作,而不是默认当做构造函数 调
用。注意和 Array 区分,Array(…)等价于 new Array(…)

typeof Number(1) // "number"
typeof String("1") // "string" Array(1, 2, 3)
// 等价于
new Array(1, 2, 3)

问题四:typeof new Number(1)的返回值是什么?
答案:“object”。

typeof new Number(1) // "object"
typeof new String(1) // "object"

instanceof
instanceof 不能用于判断原始数据类型的数据:
3 instanceof Number // false
‘3’ instanceof String // false
true instanceof Boolean // false
instanceof 可以用来判断对象的类型:
var date = new Date()
date instanceof Date // true var number = new Number()
number instanceof Number // true var string = new String()
string instanceof String // true

需要注意的是,instanceof 的结果并不一定是可靠的,因为在 ECMAScript7 规范中可以通过自定义 Symbol.hasInstance 方法来覆盖默认行为。

Object.prototype.toString
Object.prototype.toString.call(undefined).slice(8, -1) // "Undefined" 
Object.prototype.toString.call(null).slice(8, -1) // "Null" 
Object.prototype.toString.call(3).slice(8, -1) // "Number" 
Object.prototype.toString.call(new Number(3)).slice(8, -1) // "Number" 
Object.prototype.toString.call(true).slice(8, -1) // "Boolean" 
Object.prototype.toString.call('3').slice(8, -1) // "String" 
Object.prototype.toString.call(Symbol()).slice(8, -1) // "Symbol"

由上面的示例可知,该方法没有办法区分数字类型和数字对象类型,同理还有字符串类型和字符串对象类型、布尔类型和布尔对象类型
另外,ECMAScript7 规范定义了符号 Symbol.toStringTag,你可以通过这个符号自定义Object.prototype.toString 方法的行为:

'use strict' 
var number = new Number(3)
number[Symbol.toStringTag] = 'Custom' Object.prototype.toString.call(number).slice(8, -1) // "Custom"
function a () {}
a[Symbol.toStringTag] = 'Custom'
 Object.prototype.toString.call(a).slice(8, -1) // "Custom" 
 var array = []
array[Symbol.toStringTag] = 'Custom' 
Object.prototype.toString.call(array).slice(8, -1) // "Custom" 

因为 Object.prototype.toString 方法可以通过 Symbol.toStringTag 属性来覆盖默认行 为,所以使用这个方法来判断数据类型也不一定是可靠的

Array.isArray
Array.isArray(value)可以用来判断 value 是否是数组:
Array.isArray([]) // true
Array.isArray({}) // false
(function () {console.log(Array.isArray(arguments))}()) // false

3、创建对象的几种方式

创建方法
1、字面量对象 // 默认这个对象的原型链指向 object var o1 = {name: ‘01’};
2、通过 new Object 声明一个对象
var o11 = new Object({name: ‘011’});
3、使用显式的构造函数创建对象
var M = function(){this.name=‘o2’};
var o2 = new M();
o2.proto=== M.prototype
o2 的构造函数是 M
o2 这个普通函数,是 M 这个构造函数的实例
4、object.create() var P = {name:‘o3’};
var o3 = Object.create§;

4、js内置的常用对象有哪些?并列举该对象的常用方法

Array数组、Boolean、Date、Error、Math、Number、Obejct、RegExp、String、Function

Array
reverse() 将数组中各元素颠倒顺序
delete 运算符 只能删除数组元素的值,而所占空间还在,总长度没变(arr.length)
shift() 删除数组中第一个元素,返回删除的那个值,并将长度减 1
pop() 删除数组中最后一个元素,返回删除的那个值,并将长度减 1
unshift() 往数组前面添加一个或多个数组元素,长度要改变。arrObj.unshift(“a” ,
“b,“c”)
push() 往数组结尾添加一个或多个数组元素,长度要改变。arrObj.push(“a” ,“b”,
“c”)
concat( ) 连接数组
slice( ) 返回数组的一部分
sort( ) 对数组元素进行排序
splice( ) 插入、删除或替换数组的元素

Boolean 布尔对象
Boolean.toString( ) 将布尔值转换成字符串
Boolean.valueOf( ) Boolean 对象的布尔值

Date
Date.getDate( ) 返回一个月中的某一天
Date.getDay( ) 返回一周中的某一天
Date.getFullYear( ) 返回 Date 对象的年份字段
Date.getHours( ) 返回 Date 对象的小时字段
Date.getMilliseconds( ) 返回 Date 对象的毫秒字段
Date.getMinutes( ) 返回 Date 对象的分钟字段
Date.getMonth( ) 返回 Date 对象的月份字段
Date.getSeconds( ) 返回 Date 对象的秒字段
Date.getTime( ) 返回 Date 对象的毫秒表示

Error
Error 异常对象
Error.message 可以读取的错误消息
Error.name 错误的类型
Error.toString( ) 把 Error 对象转换成字符串
EvalError 在不正确使用 eval()时抛出
SyntaxError 抛出该错误用来通知语法错误
RangeError 在数字超出合法范围时抛出
ReferenceError 在读取不存在的变量时抛出
TypeError 当一个值的类型错误时,抛出该异常
URIError 由 URl 的编码和解码方法抛出
Math
Math.ceil() 向上取整(整数加 1,小数去掉)
Math.floor() 向下取整(直接去掉小数)
Math.round() 四舍五入

Number
Number.toString( ) 将—个数字转换成字符串
Number.valueOf( ) 返回原始数值

Object
Object.toString( ) 定义一个对象的字符串表示

RegExp
RegExp.exec( ) 通用的匹配模式
RegExp.global 正则表达式是否全局匹配
RegExp.ignoreCase 正则表达式是否区分大小写
RegExp.lastIndex 下次匹配的起始位置
RegExp.source 正则表达式的文本
RegExp.test( ) 检测一个字符串是否匹配某个模式
RegExp.toString( ) 把正则表达式转换成字符串

String
substr() 在原始字符串,返回一个子字符串
substring() 在原始字符串,返回一个子字符串
split() 将一个字符串转成数组
concat( ) 连接字符串
lastIndexOf( ) 从后向前检索一个字符串

Function
Function.apply( ) 将函数作为一个对象的方法调用
Function.arguments[] 传递给函数的参数
Function.call( ) 将函数作为对象的方法调用
Function.caller 调用当前函数的函数
Function.length 已声明的参数的个数
Function.prototype 对象类的原型
Function.toString( ) 把函数转换成字符串

5、===与 = =的区别

===:三个等号我们称为等同符,当等号两边的值为相同类型的时候,直接比较等号两边
的值,值相同则返回 true,若等号两边的值类型不同时直接返回 false。也就是说三个等号
既要判断值也要判断类型是否相等
= =:两个等号我们称为等值符,当等号两边的值为相同类型时比较值是否相同,类型不同
时会发生类型的自动转换,转换为相同的类型后再作比较。也就是说两个等号只要值相等
就可以

6、怎么判断两个对象相等

思路是要遍历对象的所有键名和键值是否都一致

1、判断两个对象是否指向同一内存
2、使用 Object.getOwnPropertyNames 获取对象所有键名数组
3、判断两个对象的键名数组是否相等
4、遍历键名,判断键值是否都相等

7、函数提升与变量提升的区别

变量提升
简单说就是在 JavaScript 代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提 升至其对应作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被升到最顶端
举例来说:
console.log(a); //
undefined var a = 3; //预编译后的代码结构可以看做如下运行顺序 var a; // 将变量 a 的声明提升至最顶端,赋值逻辑不提升。 console.log(a); // undefined a = 3; // 代码执行到原位置即执行原赋值逻辑
函数提升
函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升
函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上

在js中变量和函数的声明会提升到最顶部执行
函数的提升高于变量的提升
函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找。
匿名函数不会提升。

8、什么是闭包?

闭包就是能够读取其他函数内部变量的函数
闭包基本上就是一个函数内部返回一个函数

特点:1.函数嵌套函数

​ 2.内部函数可以访问外部变量

​ 3.参数和变量不会被回收(回收牵扯出全局变量和局部变量,因为全局变量在页面关闭后销毁,比较占内存资源。局部变量在函数执行完毕后销毁,闭包保护局部变量不会在函数执行完被回收也就是销毁)

不能滥用闭包,会导致内存泄漏(本应该会回收的变量没有被回收)

9、箭头函数的特点

不需要function关键字来创建函数
省略return关键字
改变this指向

10、简述this的含义

this 指的是调用函数的那个对象
this 在没有运行之前不能知道代表谁;js的this 指向是不确定的;
和定义没有关系,和执行有关.执行的时候,点前面是谁,this 就是谁;
自执行函数里面的this 代表的是 window
定时器书写的时候,window可以省略掉;定时器执行的时候,里面的this 代表的也是 window ;
this 是js的一个关键字,随着函数使用场合不同,this 的值会发生变化。
如果有new关键字,this指向new出来的对象
在事件中,this指向触发这个事件的对象

11、js中new操作符主要干了什么?

创建一个空对象,并且this变量引用该对象,同时还继承了该函数的原型
属性和方法被加入到this引用的对象中
新创建的对象this所引用,并且最后隐式返回this

12、js中call、apply、bind作用和区别

Call
第一个参数是this指向的新环境 第二个参数及以后的参数,是传递给调用者新环境的参数,调用者此时在新环境被中执行 第一个参数可以为函数也可以为this,如果为null,则表示执行window 用来改变this指向

Apply
第一个参数是this指向的新环境 第二个参数要传递给新环境的参数数组

Bind
第一个参数是this指向的新环境 第二个参数要传递给新环境的参数 返回一个改变this 指向的新函数,对原函数没有影响

13、什么是作用域?全局作用域和局部作用域?

概念:代码(变量)可以使用的范围就是作用域。主要是为了提高程序的可靠性,也是为了减少命名冲突

全局作用域和局部作用域
全局作用域:指的是整个js文件,定义在全局中的全局变量,可以在局部作用域中使用,函数内部没有声明直接赋值的变量也叫全局变量
局部作用域:主要指的是函数作用域,函数内部也就是局部作用域
在函数内部var定义的变量-,叫做局部变量,局部变量无法被外部获取

14、什么是事件冒泡?怎么阻止事件冒泡?

概念:当我们点击子元素触发父元素的事件,这种现象,我们叫做事件冒泡,即由子元素向祖先元素传播,就像气泡从水底上浮
event.stopPropagation();阻止事件冒泡

15、什么是事件委托?

通俗的讲,子代有事,让父级执行,当我们点击li时,子元素会通过事件的冒泡来触发父元素的事件,主要是通过事件冒泡
原理: 不要给每个子节点单独设置事件监听器,而是事件监听设置在其父节点上,然后利用冒泡原理影响设置每个子节点

16、面向对象的特点?

​ 抽象:把主要特征跟问题抽象出来

​ 封装:把方法写在内部,外部调用

​ 继承:可以从父类继承方法和属性,而子类又有自己独特的属性

17、简述深浅拷贝以及深拷贝的方法

浅拷贝:基本数据类型拷贝的是值,引用数据类型拷贝的是地址
深拷贝:引用数据类型拷贝的是开辟新地址中的值

深拷贝的方法
对象和字符串的相转化
​ var a = JSON.stringify(one);//先转字符串再转对象​ var b = JSON.parse(a);

封装开辟新地址的函数
​ function deepCopy(obj){​ var objs = JSON.stringify(obj);​ var newObj = JSON.parse(objs);​ return newObj;​ }

数组的解决方法
数组的解决方法,只要有返回新数组的均可以解决这个问题
slice、 concat 、split等

18、防抖与节流

节流 :在频繁接触的函数中,指的是在一定时间中只执行一次,适应于所有频繁触发的事件
防抖 : 在频繁触发的函数中,只执行最后一次,主要思路,当事件一段事件没有继续触发时,我们的事件处理函数才会执行一次

19、ajax过程?

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.

20、请解释一下 JavaScript 的同源策略

概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。

21、如何解决跨域?

jsonp跨域
document.domain + iframe 跨域
nodejs中间件代理跨域cros
后端在头部信息里面设置安全域名

22、内存泄漏

定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
js中可能出现的内存泄漏原因
全局变量
dom 清空时,还存在引用
定时器未清除
子元素存在引起的内存泄露

23、javascript的内存(垃圾)回收机制?

垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存

一般使用标记清除方法(mark and sweep), 当变量进入环境标记为进入环境,离开环境标记为离开环境
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

还有引用计数方法(reference counting), 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。

23、什么是原型、原型链?

1.任何对象都有 proto 隐式原型, 等于 构造函数 的 prototype

const obj = {}
obj.__proto__ === Object.prototype // true

2.任何函数都有 prototype 显示原型 等于 原型对象(就是一个普通对象包含公共属性)
*(通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性)

function Person () {}
Person.prototype = 原型对象
Person.prototype.constructor === Person // true<br>
const person1 = new Person
person1.__proto__ === Person.prototype // true
person1.constructor == Person // true

3.对象还具有 constructor 属性,指向构造函数(Person.prototype.constructor == Person)
4.原型链是依赖于__proto__, 查找一个属性会沿着 proto 原型链向上查找,直到找到为止。
5.特殊

// 原型链最终点是 null 
Object.prototype.__proto__ === null // true
obj.__proto__.__proto__ === null // true

每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
于是就这样一直找下去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.proto
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

24、get与post的区别

get 通过地址栏拼接参数,但是因为地址栏长度有限,所以get传输数据也有限
post 没有数据传输大小的限制
get不需要设置请求头post需要设置请求头
get请求数据可能被缓存post不会
get只能URL编码,post支持的编码格式众多

25、let、var、const区别

varletconst只有全局作用域和函数作用域有块级作用域有块级作用域存在变量提升不存在变量提升不存在变量提升可以重复声明不能重复声明不能重复声明没有死区存在暂时性死区存在暂时性死区可以先声明后赋值可以先声明 后赋值声明即赋值

26、promise对象简述

三种状态:pending(进行中),fulfilled(已成功),reject(已失败)

promise是es6引入异步编程新解决方案,语法上promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

Promise构建出来的实例存在以下方法: then() 是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数 catch() 用于指定发生错误时的回调函数 finally() 用于指定不管 Promise 对象最后状态如何,都会执行的操作

1)promise构造函数:promise(excutor){}
2)promise.protiotype.then方法
3)promise.prototype.catch方法

27、async、await

async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。是Generator函数的语法糖,并对Generator函数进行了改进。

改进:

  • 内置执行器,无需手动执行 next() 方法。
  • 更好的语义
  • 更广的适用性:co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
  • 返回值是 Promise,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用。
  • async 隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。

四、VUE

1.vue的双向绑定原理

答:通过数据劫持结合订阅者发布模式,通过Object.defineProperty(),为各个属性定义get、set方法,在数据发生改变时,给订阅者发布消息,触发相应的事件回调

每一个组件实例都有相应的watch程序实例,他会在组件渲染的过程中把属性记录为依赖,之后当依赖向的setter被调用时,会通知watch重新计算,从而导致它关联的组件得以更新

响应式:
数据响应式:vue采用的是数据劫持结合开发者订阅模式的方式,通过Object.defineProperty()来劫持,set、get在数据变动的时候,发布给订阅者,触发响应式回调

页面响应式:媒体查询、弹性盒子、百分比布局

2.MVVM、MVC

答:注意:mvvm是vue的设计思想

​ M:model,指的是后端传递的数据

​ V:view,指的是视图,也就是所看到的的界面

​ VM:view Model,视图模型,他是连接的view和model的桥梁,主要是处理业务逻辑对象

​ MVC: m:模型 v:视图 c:controller控制器,处理逻辑

3.vue的优点

答:轻量级、组件化、数据双向绑定、虚拟DOM、单页面应用(SPA:一个项目只有一个web页面应用,加载单个HTML页面,并在用户与程序发生交互时,更新该页面的局部内容,但不刷新页面)

4.为什么vue组件中的data是一个函数***

组件间数据相互不被影响

答:js中对象是一个引用数据类型,每一个组件都是一个vue的实例,组件共享data属性,只要一个实例对对象进行操作,其他的组件实例中的额数据也会发生变化。

组件中的data写成一个函数,数据就会以函数的形式定义,这样每一个组件实例就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,各个组件实例维护各自的数据。

为什么使用return返回?

不使用return会造成这个变量(数据)在项目中,变得全局可见,造成变量污染,使用return包裹,只会在当前组件中可用,不会影响到其他组件

5.VUE全家桶

vue全家桶包括:vue-router、vuex、vue-resouerce,再加上vue-cil和sass样式和组件库,就是一个完整测vue项目的核心构成

概括起来就是项目构建工具+路由+状态管理+http请求工具+样式管理/组件库

6.v-for中key的作用

答:key代表的是唯一、在项目中如果使用for不加key会报警告,渲染时会出现错误,key的作用是为了更高效的更新虚拟dom,其目的就是为了让vue可以区分

7.vue2的缺点

答:vue2是通过object.defineProperty()方法来进行数据的劫持,对象新增或者直接通过下标修改数组,界面不会自动更新

解决方法:$set(要操作的数组或者对象,下标或键值,要添加的内容)

8.什么是虚拟dom,为什么要使用虚拟dom

答:虚拟dom本质是一个js对象,用于描述视图界面结构,在vue中每个组件都有一个render函数,每一个函数都会返回一个虚拟dom数,这也意味着每一个组件都对应着一个虚拟dom树

真实的dom操作会带来大量的性能损耗,当操作节点过多时,会极大的导致渲染速度变慢,虚拟dom在数据发生改变时,新的dom树会和老的对比,然后vue中会帮我们找出最小的更新量,更新必要的虚拟dom,最后通过虚拟dom来修改真实dom

diff算法:

​ 比较新旧虚拟dom,如果节点类型相同,则比较数据,修改数据;如果节点不同,直接插入新的节点,如果给每一个节点都设置了唯一的key,就可以准确找到需要改变的内容,否则就会出现修改一个地方导致其他地方都改变的情况。

9.v-for和v-if能否一起使用

答:尽可能的v-if和v-show不要同时使用,v-for是渲染数组或者对象的,v-for的优先级高,导致每循环一次就回去v-if一次,因为v-if是通过创建和销毁来完成显示隐藏的,所以会造成不停的销毁和创建 ,造成页面的卡顿

解决方法:在v-for的外层或者内层包裹一个元素来使用v-if

10.computed和watch的区别

答:
computed:计算属性,并且有缓存,只有她所依赖的属性值发生变化computed才会重新计算,并且支持同步

watch:监听器,不支持缓存(可以在data中直接使用),监听的数据发生变化才会触发,watch支持异步,监听的函数可以接收两个参数,一个是最新的值,另一个是改变之前的值

计算属性computed :
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化

侦听属性watch:
1.不支持缓存,数据变,直接会触发相应的操作;
2.watch支持异步;
3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

2、使用场景

computed

    当一个属性受多个属性影响的时候就需要用到computed
    最典型的例子: 购物车商品结算的时候
watch
    当一条数据影响多条数据的时候就需要用watch,搜索数据

watch都有哪些属性

1)当监听一个基本数据类型时,直接使用

2)当监听一个引用数据类型时,执行回调且回调函数名字(handler)不可更改(or默认?)

开启深度监听:deep:true

开始初始执行handler函数:immediate:true

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

v-if:是真正的条件渲染,同时他也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到第一次变为真时,才会开始渲染,条件切换过程会发生销毁和重建

具有更高的切换开销,如果在运行是条件很少改变,使用v-if比较好

v-show:不管初始条件是什么,元素总是会被选二胺,并且知识简单的基于css(display:none/block)进行切换
具有更高的初始开销,如果切换非常频繁,则使用v-show比较好

12.vue的生命周期

答:
概念:vue实例从创建到销毁的过程就是生命周期,也就是从开始创建,初始化数据,编译模板,挂载dom->渲染,更新->渲染,卸载等一系列过程

beforeCreate():vue实例创建之前调用

created():vue实例创建完成

beforeMount():视图编译之前

mounted():视图编译完成,vuedom加载之后

beforeUpdate():数据改变之前

updated():数据改变之后

beforeDestory():vue销毁之前

destory():vue销毁之后

第一次页面加载触发的-生命周期

beforeCreate():vue实例创建之前调用

created():vue实例创建完成

beforeMount():视图编译之前

mounted():视图编译完成,vuedom加载之后

13.vue的指令

v-model:主要用于表单类的双向绑定,本质是一个语法糖,可以理解为一个快捷方式,是通过v-bind、v-on来实现的
主要有三个修饰符:
​ .number 将输入的字符转为有效的数字,不加则是默认字符串类型
​ .lazy 取代input,监听change事件,当发生改变的时候才会触发
​ .trim 过滤首尾空格

v-for:列表循环遍历、数组、对象、字符串、数字均可以

v-if:用来确定标签是否渲染

v-show:根据表达式的真假值,切换元素的display:block/none,当条件变化时该指令触发过渡效果

v-text:更新元素的textCount,如果需要更新部分textCount,则需要使用插值{{Mustache}}

v-on:绑定事件监听器,事件类型由参数指定,表达方式可以是一个方法的名字或者是一个内联语句,如果没有修饰符也可以省略 简写形式@

v-bind:主要是用来动态绑定属性,简写为:

v-slot:提供具名插槽或者需要接收prop的插槽,缩写为#

v-once:值渲染元素和组件一次,随后的重新渲染,元素/组件及其所有的子节点被视为静态内容并跳过,这可以用于优化更新性能

14.常见的修饰符及其作用
.stop:等同于js中event.stopPropagation(),防止事件冒泡
.prevent :等同于js中event.preventDefault(),阻止默认行为
.capture:当元素发生冒泡时,先触发带有修饰符的元素,若有多个修饰符,则由内而外触发。如 div1中嵌套div2中嵌套div3.capture中嵌套div4,那么执行顺序为:div3=》div4=》div2=》div1
.slef:只触发自己范围内的事件,不包含子元素
.once:只触发一次

15.vue组件如何进行传值的?

答:1.父组件向子组件传递数据
​ 父组件内设置要传的数据,在父组件中引用的子组件上绑定一个自定义属性并把数据绑定在自定义属性上,在子组件添加props接收即可
​ 2.子组件向父组件传递数据

​ 子组件通过vue实例方法$ emit进行触发并且可以携带参数,父组件监听使用@(v-on)绑定的事件进行监听,然后方法处理

​ 3.兄弟组件之间传递数据

​ 3.1 引入第三方 new vue 定义为 eventBus

​ 3.2)在组件中 created 中订阅方法 eventBus.$ on(“自定义事件名”,methods 中的方法名)

​ 3.3) 在另一个兄弟组件中的 methods 中写函数,在函数中发布 eventBus 订阅的方法

​ eventBus.$emit("自定义事件名”)

​ 3.4) 在组件的 template 中绑定事件(比如 click)

​ 4.祖孙之间的传值

​ provide 定义的对象会加载到子组件或者孙子组件中

​ inject 接收祖先组件中provide函数return出的内容

​ 5.可以通过vuex传值

​ 6.可以使用本地存储进行传值(cookie、localstorge、sessionStorage)

16.组件中写name会有什么作用?

项目使用keep-alive时,可搭配组件name进行缓存过滤
DOM做递归组件时需要调用自身的name
vue-dectools 调试工具里显示的组件名称是由vue中组件name决定的

17.父子组件嵌套时生命周期哦钩子函数的执行顺序

Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:

加载渲染过程 :
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程 :
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程 :
父 beforeUpdate -> 父 updated
销毁过程 :
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

18、vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

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

  • State => 基本数据,定义了应用状态的数据结构,可以在这里设置默认的初始状态。
  • Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation => 是唯一更改 store 中状态的方法,且必须是同步函数。
  • Action => 像一个装饰器,包裹mutations,使之可以异步。用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
  • Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

19、谈谈你对keep-alive的理解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

20、vue-router路由模式有几种?

vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示:

switch (mode) {
  case 'history':
    this.history = new HTML5History(this, options.base)
    break
  case 'hash':
    this.history = new HashHistory(this, options.base, this.fallback)
    break
  case 'abstract':
    this.history = new AbstractHistory(this, options.base)
    break
  default:
    if (process.env.NODE_ENV !== 'production') {
      assert(false, `invalid mode: ${mode}`)
    }
}

其中,3 种路由模式的说明如下:

  • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
  • history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
  • abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.

21、能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?

(1)hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’:
https://www.word.com#search
hash 路由模式的实现主要是基于下面几个特性:

  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
  • (2)history 模式的实现原理 HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。 唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示: window.history.pushState(null, null, path); window.history.replaceState(null, null, path); history 路由模式的实现主要基于存在下面几个特性:
  • pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
  • 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

22、谈一谈你对 nextTick 的理解?

当你修改了data的值然后马上获取这个dom元素的值,
是不能获取到更新后的值,你需要使用$nextTick这个回调,
让修改后的data值渲染更新到dom元素之后在获取,才能成功。

23、$nextTick的使用

在data()中的修改后,页面中无法获取data修改后的数据,
使用$nextTick时,当data中的数据修改后,可以实时的渲染页面

24、请说出 vue-cli 工程中每个文件夹和文件的用处?

build 文件夹是保存一些 webpack 的初始化配置。
config 文件夹保存一些项目初始化的配置
node_modules 是 npm 加载的项目依赖的模块
src 目录是我们要开发的目录:
assets 用来放置图片
components 用来放组件文件
app.vue 是项目入口文件
main.js 项目的核心文件

25、Vuex 页面刷新数据丢失怎么解决?

需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,
可以自己设计存储方案,也可以使用第三方插件。
推荐使用 vuex-persist插件,
它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,
而是直接将状态保存至 cookie 或者 localStorage中。

26、Vuex 为什么要分模块并且加命名空间?

模块: 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
当应用变得非常复杂时,store 对象就有可能会变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

命名空间: 默认情况下,模块内部的 action、mutation、getter
是注册在全局命名空间的 — 这样使得多个模块能够对同一 mutation 或 action 做出响应。
如果希望你的模块具有更高的封装度和复用性,
你可以通过添加 namespaced:true 的方式使其成为带命名的模块。
当模块被注册后,他所有 getter、action、及 mutation 都会自动根据模块注册的路径调整命名。

27、vue 中使用了哪些设计模式?

1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
3、发布-订阅模式。(vue 事件机制)
4、观察者模式。(响应式数据原理)
5、装饰器模式(@装饰器的用法)
6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,
该行为有不同的实现方案 - 比如选项的合并策略。

28、你都做过哪些 Vue 的性能优化?

这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。
对象层级不要过深,否则性能就会差。
不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
v-if 和 v-show 区分使用场景
computed 和 watch 区分场景使用
v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
防止内部泄露,组件销毁后把全局变量和时间销毁
图片懒加载
路由懒加载
异步路由
第三方插件的按需加载
适当采用 keep-alive 缓存组件
防抖、节流的运用
服务端渲染 SSR or 预渲染

五、其他内容

1、性能优化的几个方面?

资源压缩合并,减少HTTP请求
非核心代码异步加载
利用浏览器缓存
使用CDN
预解析DNS

2、异步加载?

动态脚本加载
defer
async

3、加载方式

defer是在html解析完毕才执行,如果有多个则按加载顺序执行
async是加载完毕后立即执行,如果是多个,执行顺序与加载顺序无关

4、预加载

在开发中,可能会遇到这样的情况。有些资源不需要马上用到,
但是希望尽早获取,这时候就可以使用预加载。
预加载其实是声明式的 fetch ,强制浏览器请求资源,
并且不会阻塞 onload 事件,可以使用以下代码开启预加载
link rel=“preload” href=“http://example.com”
预加载可以一定程度上降低首屏的加载时间,
因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。

5、DNS预解析

DNS 解析也是需要时间的,可以通过预解析的方式来预先获得域名所对应的 IP。

<metahttp-equiv='x-dns-prefetch-control'content='on'><linkrel="dns-prefetch"href="//yuchengkai.cn">

在https协议中默认a标签不会开启预解析,因此需要手动设置meta

6、懒执行

懒执行就是将某些逻辑延迟到使用时再计算。
该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,
就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。

7、懒加载

懒加载就是将不关键的资源延后加载。

懒加载的原理就是只加载自定义区域(通常是可视区域,
但也可以是即将进入可视区域)内需要加载的东西。对于图片来说,
先设置图片标签的 src 属性为一张占位图,
将真实的图片资源放入一个自定义属性中,当进入自定义区域时,
就将自定义属性替换为 src 属性,这样图片就会去下载资源,实现了图片懒加载。

懒加载不仅可以用于图片,也可以使用在别的资源上。比如进入可视区域才开始播放视频等等。
标签: 前端 面试

本文转载自: https://blog.csdn.net/liqiannan8023/article/details/128669585
版权归原作者 简单长庚 所有, 如有侵权,请联系我们删除。

“【面试宝典】2023前端面试题”的评论:

还没有评论