2023前端面试题总汇(持续更新中...)

目录

一、HTML、CSS篇

1、HTML、XHTML、XML 有什么区别?⭐

2、 XML和JSON的区别?

3、是否了解W3C的规范?⭐

4、什么是语义化标签?⭐⭐

5、常用的块级元素和行内元素有哪一些? ⭐

6、行内元素和块级元素的区别?⭐ 

7、css盒子模型有几种类型?它们区别是什么 ⭐ 

8、标签上title与alt属性有什么区别?

9、 H5新特性有哪些?⭐⭐

10、css3的新特性有哪些?⭐⭐

11、css的引用有哪些,link和@import的区别?

12、href和src的区别?⭐

13、CSS常用尺寸单位有哪些?应用场景?

14、移动端适配方案有哪些?⭐

15、什么是浮动?

16、清除浮动有哪些方法? ⭐

17、css选择器有哪些?⭐

18、CSS 样式覆盖规则?⭐

19、CSS 样式的优先级?⭐⭐

20、display: none 和 visibily: hidden 区别? 

21、相对定位,绝对定位,固定定位的区别?

22、说几个未知宽高元素水平垂直居中方法? 

二、JS 篇

1、JS数据类型有哪些?区别?⭐⭐⭐

2、JS中检测数据类型的有哪些?⭐⭐

3、JS中的栈和堆是什么?优缺点?⭐⭐⭐

4、深克隆和浅克隆?⭐⭐⭐

5、JS垃圾回收机制?⭐

6、JS哪些操作会造成内存泄露?⭐⭐

7、闭包?⭐⭐

8、什么是原型链?⭐⭐⭐

9、JS继承的方法有哪些?优缺点?⭐

10、new操作符具体都干了什么?⭐⭐

11、JS的几种具体异常类型(报错)

12、什么是事件冒泡?什么是事件委托?

13、事件对象? 

14、undefined 和 null 区别?⭐

15、说一说伪数组和数组的区别?

16、对于数组去重都有哪些方法?⭐⭐ 

17、 对join、push、split、splic、slice的理解?

18、说一下this指向?⭐⭐ 

19、 js中call、apply、bind有什么区别?⭐⭐

20、箭头函数和普通函数有什么区别?⭐⭐ 

21、JQ对象和DOM元素之间如何转换? 

22、JS模块化有哪些?

23、如何操作DOM元素?

24、防抖与节流的区别,并分别用代码表示 

24、数组迭代的方法有哪些? 

25、for循环和forEach有什么区别?

26、使用JQ和vue的区别?

三、ES6 篇

1、ES6新增的内容有哪些?⭐⭐⭐

2、ES6中,Set和Map的区别?⭐⭐⭐

3、map和forEach的区别?

4、es6 中的箭头函数?⭐⭐⭐

5、什么是扩展运算符,用于什么场景?⭐⭐

6、JS变量提升?⭐⭐

7、怎么实现Module模块化?

8、同步和异步的区别?同步函数和异步函数的区别?⭐

9、JS的执行顺序?同步任务和异步任务?⭐⭐⭐

10、 promise和async await区别?⭐⭐⭐

四、TS 篇

五、VUE 篇

六、uni-app 篇

七、HTTP 请求篇

八、git 篇

九、其他模块

十、手撕代码


一、HTML、CSS篇

1、HTML、XHTML、XML 有什么区别?⭐

  1. XML: XML 是可扩展标记语言,主要是用来存储和传输数据,而非显示数据,可以用来标记数据,定义数据类型,允许用户对自己的标记语言进行定义。
  2. HTML:HTML 是超文本标记语言,主要是用来描述网页的一种标记语言,通过标记标签来描述网页。
  3. XHTML:XHTML 是可扩展超文本标记语言,XHTML 基于 XML 和 HTML 而来,也是用来描述网页的标记语言,是更严格的 HTML 版本。例如:XHTML 元素必须被正确地嵌套,标签名必须用小写字母, 文档必须拥有根元素,对于图片需添加 alt 属性等。XHTML 和 HTML 4.01 几乎是相同的,XHTML 是 W3C 标准。
  4. XML和HTML区别:XML 相比 HTML 语法要求严格。HTML 是预定义的,XML 标签是免费的、自定义的、可扩展的。HTML 的设计目的是显示数据并集中于数据外观,XML 的设计目的是描述数据、存放数据并集中于数据的内容。XML 是一种跨平台的,数据处理和传输的工具。总的来说,XML用来传输数据,而 HTML 和 XHTML 用来描述网页,XHTML 比 HTML 更为严格。 

2、 XML和JSON的区别?

  1. JSON:JSON 是一种轻量级的数据交换格式,它基于 JavaScript 的一个子集,简单的说 JSON 就是一串字符串用于不同平台的数据交换。
  2. XML:XML 是可扩展标记语言,是标准通用标记语言 (SGML) 的子集,XML 主要是用来存储和传输数据,而非显示数据,可以用来标记数据、定义数据类型,允许用户对自己的标记语言进行定义。
  3. JSON和XML区别:JSON 数据的体积小,传递速度更快,与 JavaScript 数据交互更加方便,更容易解析处理。XML 对数据的描述性比较好。JSON 支持数组,XML 不支持数组。JSON 不支持命名空间,XML 支持命名空间。JSON 容易阅读,XML 难以阅读和解释。JSON 不使用结束标记,XML 有开始和结束标签。JSON 的安全性较低,不支持注释,仅支持 UTF-8 编码。XML 比 JSON 更安全,支持注释,支持各种编码。

3、是否了解W3C的规范?⭐

  • w3c 标准指的是万维网联盟标准,万维网联盟标准指的不是一个标准,而是一系列标准的集合。web 可以简单分为结构、表现、行为三部分,三部分独立开来使其模块化,w3c 是对 web 做出规范,使代码更加严谨,做出来的网页更加容易使用和维护。
  • 结构标准主要包括 XHTML 和 XML ,比如像标签闭合、标签元素和属性名字小写、标签不乱嵌套、属性必须有属性值、属性值必须用引号括起来、特殊符号用编码表示、定义语言编码等。标签规范可以提高搜索引擎对页面的抓取效率,对 SEO (搜索引擎优化) 很有帮助,越规范的网站搜索排名越靠前。
  • 表现标准主要包括 CSS,行为标准主要包括对象模型(像 W3C DOM,ECMAScript),比如说尽量使用外链的 css 和 js 脚本,提高页面的渲染效率,尽量少使用行内样式,类名要做到见名知意。遵循 w3c 标准可以让我们的页面,我们的程序能够支持所有浏览器,能够满足尽可能多的用户。
  • W3C 标准的体现,也就是说是开发者在开发过程中怎么去准守 W3C 标准,其实这里面很多规范是为了 XHTML 的,jQurry 不符合 W3C 标准。

4、什么是语义化标签?⭐⭐

语义化标签就是标签语义化,让标签有自己的含义,使浏览器和搜索引擎能直观的认识标签的用途和内容。虽然可以采用 DIV + CSS 的方式布局页面,但 DIV 标签本身没有特殊含义,文档结构不够清晰,不利于浏览器对页面的读取,在分离 CSS 样式后,体验不友好。使用语义化标签可以使代码结构清晰,可读性高,便于团队开放和维护。在页面没有加载 CSS 的情况下也能呈现良好的结构,易于阅读。有利于SEO(搜索引擎优化)。

5、常用的块级元素和行内元素有哪一些? ⭐

6、行内元素和块级元素的区别?⭐ 

  • 行内元素:默认不换行,设置宽高无效 (默认宽度是本身内容宽度),不能包含块级元素,只能包含文本或者其它行内元素,设置 margin,padding 上下无效。
  • 块级元素:默认换行,独占一行,可设置宽高 (宽度是父容器的100%),块级元素可以嵌套任意元素,块级文字不能放入其他块级元素。
  • 行内块元素:综合块级元素与行内元素的特性,可设宽高(默认是内容宽高),也可以设置内外边距。
  • 转换:display:block,display:inline,display:inline-block。

7、css盒子模型有几种类型?它们区别是什么 ⭐ 

  • 根据盒子大小的计算方式不同,css 盒子模型分成了两种类型,分别是 W3C 标准盒子模型和怪异盒子模型也叫 IE 盒子模型。
  • 标准盒子模型内容的宽度等于设置的宽度,盒子的宽度 = 内容的宽度 + padding*2 + margin*2 + border*2。
  • IE盒子模型内容宽度 = 设置的宽度 - padding*2 - margin*2 - border*2,盒子宽度等于设置的宽度。
  • 默认情况下都是标准盒子模型,设置 IE 盒子模型:box-sizing:border-box,设置标准模型:box-sizing:content-box 

8、标签上title与alt属性有什么区别?

  1. alt 是给搜索引擎识别,在图像无法显示时的替代文本。

  2. title 是元素的注释信息,主要是给用户解读。

  3. 当鼠标放到文字或是图片上时有 title 文字显示。在 IE 浏览器中 alt 起到了 title 的作用,变成文字提示。

9、 H5新特性有哪些?⭐⭐

  1. 语义化标签
    <header> 定义文档的头部区域
    <nav> 定义导航链接
    <article> 内容标签
    <section> 定义文档某个区域
    <aside> 侧边栏标签
    <footer> 定义了文档的尾部区域
    <figure> 规定独立的流内容(图像、图表、照片、代码等)
    <figcaption> 定义 <figure> 元素的标题
  2. 增强表单功能 (类型和属性)
  3. 音频视频:<Audio> 、<video>
  4. 绘图 (画布):<Canvas>
  5. SVG 绘图
  6. 地理位置
  7. 拖拽 APL
  8. WebStorage (本地存储:LocalStorage / SessionStorage )

10、css3的新特性有哪些?⭐⭐

  1. 选择器:层级选择器,属性选择器,状态伪类选择器,结构伪类选择器,伪元素选择器
  2. 文本效果:文本阴影 ,文本自动换行,文本溢出,(单词拆分,文本拆分)
  3. 边框:圆角边框 border-radius,边框阴影 box-shadow,边框图片 border-image
  4. 背景:渐变背景,多重背景 (设定背景图像的尺寸,指定背景图像的位置区域,背景的绘制)
  5. 透明度:opacity ( 取值0-1,通常用于做元素的遮罩效果)
  6. 高斯模糊:filter
  7. 渐变:background: linear-gradient (线性渐变,径向渐变 ,文字渐变)
  8. 过渡:transition
  9. 2D转换 / 3D转换: transform
  10. 动画:Animation (@keyframes 动画帧)
  11. 媒体查询:@media
  12. 多列布局 (兼容性不好,还不够成熟)
  13. 弹性布局 (flex)
  14. 网格布局

11、css的引用有哪些,link和@import的区别?

css 的引用有哪些:

  1. 内联方式(直接在 html 标签中的 style 样式)
  2. 嵌入方式(在 < style > 标签下书写 css 代码)
  3. 链接方式(使用 link 引入外部的 css 文件)

 link 和 @import 的区别:

  1. link 和 import 写法不同,link 通过 <link> 标签的 href 属性引入,import 通过 @import url() 引入。
  2. link 是 XHTML 标签,还可以定义其他事务,@import 属于 CSS 范畴,只能加载 CSS。
  3. link 无兼容问题,@import 兼容 IE5 以上。
  4. link 支持使用 Javascript 控制 DOM 去改变样式,@import 不支持改变样式。
  5. link 是连接整个 css 文件,@import 可以模块化引入 css 文件。
  6. link 引用 CSS 时,在页面加载时同时加载 css,而 @import 会把 css 文件放在页面的最底部,导致 css 最后才加载完毕,等到页面完全加载才加载 css,导致页面留白时间长,影响用户体验。

12、href和src的区别?⭐

  1. 请求资源不同:href 超文本引用,用来建立当前元素和文档之间的连接,常用的是link、a 标签。src 会将指向的资源下载并引用到当前文档中,常用的标签有 script,img,iframe 标签。
  2. 作用结果不同:href 用于在当前文档和引用资源之间确立联系,src 用于替换当前内容。
  3. 浏览器解析方式不同:herf 引用的资源时,浏览器会将其识别为 CSS 文档,并行下载资源并且不会停止对当前文档的处理。当浏览器解析到 src 时,会暂停其他资源的下载和处理,直接将该资源下载,编译,执行完毕。

13、CSS常用尺寸单位有哪些?应用场景?

  1. px:像素,相对长度单位,它的大小取决于屏幕的分辨率,是一个固定值,不能够自适应。
  2. em:相对长度的单位,相对于当前对象内文本的字体尺寸,未设置则默认是浏览器默认字体尺寸。
  3. rem:CSS3 中新增的一个相对长度单位,相对于根元素 <html> 的 font-size 字体大小,根元素字体大小未设置,使用浏览器默认字体大小。

  4. vw:相对于视口的宽度。视口被均分为100单位的 vw。

  5. vh:相对视口高度,视口被均分为100单位的 vh。

  6. vmin:相对于视口宽度或高度中较小的那个。其中最小的那个被均分为100单位的 vmin。

  7. vmax:相对于视口宽度或高度中较大的那个。其中最大的那个被均分为100单位的 vmax。

  8. cm:厘米,绝对长度单位。

  9. mm:毫米,绝对长度单位。

  10. in:英寸,绝对长度单位。

  11. %:百法比

应用场景:

  1. 在移动端网页开发中,页面要做成响应式的,可使用 rem 配合媒体查询实现。原理:通过媒体查询,能够在屏幕尺寸发生改变时,重置 html 根元素的字体大小,页面中的元素都是使用rem 为单位设置的尺寸,因此只要改变根元素字体大小,页面中的其他元素的尺寸就自动跟着修改。
  2. 利用 vw 和 rem 实现响应式。原理:由于 vw 被更多浏览器兼容之后,在做移动端响应式页面时,通常使用 vw 配合 rem。原理是使用 vw 设置根元素 html 字体的大小,当窗口大小发生改变,vw 代表的尺寸随着修改,无需加入媒体查询,页面中的其他元素仍使用 rem 为单位,就可实现响应式。

14、移动端适配方案有哪些?⭐

vw、rem、em、rpx、%

15、什么是浮动?

设置浮动的图片,可以实现文字环绕图片。设置了浮动的块级元素可以排列在同一行。设置了浮动的行内元素可以设置宽高。浮动造成的影响:使盒子脱离文档流,如果父级盒子没有设置高度,需要被子盒子撑开,那么这时候父级盒子的高度就塌陷了,同时也会造成后面的盒子布局受到影响。

16、清除浮动有哪些方法? ⭐

清除浮动,主要是为了解决父级元素因为子级浮动引起的内部高度为 0 的问题

  1. 父级div定义height (只适合高度固定的布局)
  2. 结尾处加空div标签然后添加一个clear:both样式 (浮动多的话要加很多个div)
  3. 父级 div 定义 overflow:hidden 超出盒子部分会被隐藏 (不推荐)
  4. 父级div定义伪类:(推荐)
     clearfix:after
         {
              content:"";
              display:block;
              visibility:hidden;
              height:0;
              line-height:0;
              clear:both;
          }

17、css选择器有哪些?⭐

基本选择器:

  1. 标签选择器    ( div { } )
  2. id 选择器       ( id=”a”, #a { } )
  3. 类选择器 class (class=”b”, .b { } )
  4. 通配符选择器   ( * { } )

 CSS3新增选择器: 

  1. 层级选择器:
    后代选择器 ul li { } : 选择子类元素,包括间接子类
    子代选择器 ul>li { } :选择子类元素,只包括直接子类
    相邻兄弟选择器 div+p { } : 选择紧跟在 div 元素后面的 p 元素
    通用兄弟选择器 div~p { } : 选择 div 元素后面的所有 p 元素
    共享选择器 div1,div2 { } :选择所有元素
  2. 状态伪类选择器
  3. 结构伪类选择器
  4. 表单伪类选择器
  5. 伪元素选择器
  6. 属性选择器

18、CSS 样式覆盖规则?⭐

  • 规则一:由于继承而发生样式冲突时,最近祖先获胜。
  • 规则二:继承的样式和直接指定的样式冲突时,直接指定的样式获胜。
  • 规则三:直接指定的样式发生冲突时,样式权值高者获胜。
  • 规则四:样式权值相同时,后者获胜。
  • 规则五:!important 的样式属性不被覆盖。

19、CSS 样式的优先级?⭐⭐

  1. 引入方式:内联样式的优先级高于嵌入和外链,嵌入和外链的选择器相同就看他们在页面的插入顺序,后面插入的会覆盖前面的。
  2. 选择器优先级:id 选择器高于 ( 类选择器/伪类选择器/属性选择器 ) 高于 ( 标签选择器/后代选择器/伪元素选择器 ) 高于 ( 子选择器/相邻选择器 ) 高于通配符 *。
  3. 继承样式:继承样式是所有样式中优先级比较低的,浏览器默认样式优先级最低。
  4. !important:!important 最高权重,无论引入方式是什么,选择器是什么,它的优先级都是最高的。所以 !important 使用要谨慎,一定要优先考虑使用样式优先级的规则来解决问题而不是 !important 。只有在需要覆盖全站或外部 CSS 的特定页面中使用 !important。永远不要在插件中使用 !important ,永远不要在全站范围的 CSS 代码中使用 !important.

!important >> 内联样式 >> id 选择器 >> 类选择器/伪类选择器/属性选择器 >> 标签选择器/后代选择器/伪元素选择器 >> 子选择器/相邻选择器 >> 通配符 * >> 继承样式 >> 浏览器默认样式 

20、display: none 和 visibily: hidden 区别? 

  1. display:none:隐藏对应的元素,整个元素消失不占空间。
  2. visibily:hidden:隐藏对应的元素,元素还会占用空间。
  3. disapaly 还可以转换元素类型,可以转换成块级元素、行内元素,行内块元素、弹性布局、网格布局等。visibility 只能做隐藏。

21、相对定位,绝对定位,固定定位的区别?

  1. position:relative:相对定位,相对于自己进行定位。

  2. position:absolute:绝对定位,相对于有相对定位的父级元素进行定位,没有就找 body。

  3. position:fixed:固定定位,相对于浏览器定位。

22、说几个未知宽高元素水平垂直居中方法? 

  • 绝对定位:通过 left,top 和 transform 属性实现水平垂直居中,其中 translate 属性取值为负数时表示向左和向下移动。这种方式兼容性好,被广泛使用的一种方式。
<style>
    .box {
        position: absolute;
        width: 100px;
        height: 100px;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
</style>
  • 弹性布局:设置父级为弹性盒子:display:flex ,设置水平和垂直居中:justify-content:center、align-items:center。这种方式代码简洁,但是兼容性 ie11 以上支持。
<style>
    .box {
        width: 400px;
        height: 300px;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 1px solid black;
    }
    .child {
        width: 200px;
        height: 150px;
        background-color: red;
    }
</style>
<body>
    <div class="box">
        <div class="child"></div>
    </div>
</body>
  • 网格布局:设置父级为网格元素:display: table-cell,设置水平和垂直居中:justify-content:center、align-items:center。这种方式代码简洁,但是兼容性 ie10 以上支持
  • 表格布局  :设置父级为表格元素:display: table-cell,内部元素水平和垂直居中:text-align: center、vertical-align: middle,设置子元素为行内块:display: inline-block。兼容性好。
<style>
    .box {
        width: 400px;
        height: 300px;
        display: table-cell;
        text-align: center;
        vertical-align: middle;
        border: 1px solid black;
    }
    .child {
        width: 200px;
        height: 150px;
        background-color: red;
        display: inline-block;
    }
</style>
<body>
    <div class="box">
        <div class="child"></div>
    </div>
</body>

二、JS 篇

1、JS数据类型有哪些?区别?⭐⭐⭐

JS 的数据类型分为两类,分别是基本数据类型和引用数据类型。它们主要区别是在内存中的存储方式不同。

  • 基本数据类型:number 数字、string 字符串、boolean 布尔值、null 空值、undefined 未定义、symbol 唯一值、BigInt 最大值。基本数据类型有固定的大小和值,存放在栈中,可以直接访问,而引用数据类型不确定大小,但是其引用地址是固定的,因此,它的地址存在栈中,指向存储在堆中的对象。
  • 引用数据类型:Object (包括普通对象,数组,正则,日期,Math 数学函数等)。引用数据类型是存放在堆中的对象,在栈中保存的是对象在堆中的引用地址(引用变量),通过引用地址可以快速查找到保存在堆中的对象。
  • Symbol 是 Es6 新出的一种数据类型,这种数据类型的特点就是没有重复的数据,可以做 object 的 key。
  • BigInt 也是 ES6 新出的一种数据类型,BigInt 可以表示任意大的整数,能够解决解精度缺失的问题 (超过 Number 类型支持范围的数值都会失去精度)。使用方法:(1) 整数末尾直接加n:647326483767797n。(2) 调用 BigInt() 构造函数:BigInt("647326483767797")。

2、JS中检测数据类型的有哪些?⭐⭐

  • typeof:常用于判断基本数据类型,除了 null 检测为 object。对于引用数据类型除了 function 返回 function,其余全部返回 object。
  • instanceof:主要用于检测引用数据类型,不适合用来检测基本数据类型。如果检测的类型在当前实例的原型链上,则返回 true,说明这个实例属于这个类型,否则返回 false。例如: A instanceof B判断 B 在不在 A 的原型链上,如果在就返回 true,如果找到原型链的尽头 null 都没找到,就返回 false。(由于原型链的指向可以随意改动,导致检测不准确)
  • constructor:获取实例的构造函数判断和某个类型是否相同,如果相同就说明该数据是符合那个数据类型的。使用方法是:"实例.constructor"。constructor 可以检测出除了 undefined 和 null 以外的其他类型,因为 undefined 和 null 没有原生构造函数。(不可靠,容易被修改)
  • object.prototype.toString.call( ):适用于所有类型的判断检测,检测方法是: Object.prototype.toString.call(数据) ,返回的是该数据类型的字符串。

3、JS中的栈和堆是什么?优缺点?⭐⭐⭐

JS 的变量都储存到内存中,内存中开辟了两个区域储存变量,分别是栈区域和堆区域。 栈与堆实际上是操作系统对进程占用的内存空间的两种管理方式。

栈:

  1. 栈是一种先进后出的数据解构,由操作系统自动分配内存空间,自动释放,占固定的大小空间。
  2. 栈存储的是基本数据类型的值以及引用数据类型的引用地址。
  3. 栈中存储的数据的生命周期随着当前环境的执行完成而结束。

堆: 

  1. 堆由操作系统动态分配内存空间,大小不定也不会自动释放,一般由程序员分配释放也可由垃圾回收机制回收。
  2. 栈存储的是对象和复杂数据结构,存储的是对象的实际数据,而不是对象的引用。
  3. 引用数据类型只有在引用的它的变量不在时,被垃圾回收机制回收。

栈和堆的优缺点: 

  1. 栈相对于堆存取速度更快,且栈内存中数据是可以共享的,但内存空间有限。
  2. 堆存取效率相对较低,但内存空间大。
  3. 栈内存可以及时得到回收,相对来说更容易管理内存空间,但存储在栈中的数据大小和生存期必须是确定的,缺乏灵活性。
  4. 堆的内存是操作系统动态分配的,方便存储和开辟内存空间。有垃圾回收机制,生存周期比较灵活。

4、深克隆和浅克隆?⭐⭐⭐

浅克隆:

  1. 克隆对象的第一层属性。
  2. 如果是基本数据类型,直接将存储在栈中的值赋值给对应的变量,原始值改变不会影响。
  3. 如果是引用数据类型,则克隆的是对象的引用地址,改变引用地址,新对象也会跟着改变,想要改变这种继承的现象就要使用深度克隆。
  4. 在 JS 中可以通过 Object.assign( ) 或者扩展运算符 ... 合并对象实现浅克隆。

 深克隆:

  1. 克隆对象各个层级的属性。
  2. 深克隆是指创建一个与原对象完全相同的新对象 (数据源不同,数据地址已变化)。
  3. 可以通过递归的方式实现深克隆,也可以通过简单粗暴的方式实现 JSON.parse (JSON.stringify(obj))。但需要注意:时间对象会变成字符串的形式。RegExp、Error 对象序列化的结果将只得到空对象。函数、undefined 序列化的结果会把函数或 undefined 丢失。NaN、Infinity 序列化的结果会变成 null。如果对象中存在循环引用的情况也无法正确实现深拷贝。JSON.stringify() 只能序列化对象的可枚举的自有属性。

5、JS垃圾回收机制?⭐

  • 内存泄漏:JS 代码运行时,需要分配内存空间存储变量和值,当这些变量不再作用时,需要释放内存,如果没有及时释放,就会引起内存泄漏,堆积起来会影响性能甚至造成系统崩溃。垃圾回收机制就是为了防止内存泄漏,及时释放不再使用的内存,提高程序性能。
  • 垃圾回收机制:垃圾回收机制是一种自动管理内存的机制,它会自动监测和回收不再使用的对象,从而释放内存空间。实现的原理主要有标记清除、引用计数、复制算法。
  •  标记清除算法:垃圾回收器会定期扫描内存中的对象,标记那些可达对象和不可达对象。可达对象指的是正在被使用的对象。不可达对象指的是不再被引用的对象。垃圾回收器会将不可达对象标记为垃圾对象,并将他们从内存中清除。该算法的优点是可以处理循环引用的情况,缺点是由于垃圾回收器的工作需要消耗一定的系统资源,因此如果程序中存在大量的内存占用或者存在频繁创建和销毁对象的操作,执行垃圾回收操作的时间会比较长,对性能造成一定的影响。
  • 引用计数算法:垃圾回收器会记录每个对象被引用的次数,当对象被引用的次数为0时,该对象就会被清除。该算法的优点是实现较为简单,但无法处理循环引用的情况,即两个对象相互引用,但是它们的引用次数都不为 0,导致内存无法被释放,可能会导致内存泄漏。
  • 复制算法:将内存空间划分为两个相等的区域,每次只使用一个区域,这个区域满时,将其中存活的对象复制到另外一个区域,再将原区域的对象全部清除。优点是可以避免由于产生大量内存碎片而引发的内存分配失败问题。

存在问题?怎么优化?

虽然浏览器可以自动的进行垃圾回收,但是当代码比较复杂时,垃圾回收对性能的消耗比较大,所以应该尽量减少垃圾回收。需要根据具体应用的需求和环境进行优化。

  1. 对数组进行优化。清空数组时,赋值为[ ],同时将数组的长度设置为0。
  2. 对象复用,尽量减少对象的创建和销毁次数。
  3. 不再使用的对象就设置为 null。
  4. 函数优化,函数功能单一化。
  5. 尽早释放资源。
  6. 使用闭包,在闭包中的变量不会被垃圾回收机制回收。

6、JS哪些操作会造成内存泄露?⭐⭐

  1. 意外的全局变量。由于使用未声明的变量而意外的创建了一个全局变量,而使用这个变量一直留在内存中无法被回收。
  2. 没有清理的DOM元素引用。获取一个DOM元素的引用,元素被删除了,由于保留了元素的引用,所以也无法被回收。
  3. 被遗忘的定时器或者回调函数。
  4. 闭包。

7、闭包?⭐⭐

什么是闭包?

因为作用域链的存在,函数的内部可以直接读取全局变量,而函数内部无法读取另一个函数内部的局部变量,如果想读取函数内部的局部变量,可以通过闭包来实现。闭包就是在一个函数内部创建另外一个函数,让你可以在一个内层函数中访问到外层函数的局部变量。简单来说,闭包就是可以读取其他函数内部局部变量的函数,本质上,闭包是将函数内部和函数外部连接起来的桥梁。

为什么要使用闭包?

  1. 局部变量无法共享和长久的保存,而全局变量可能造成变量污染。
  2. 闭包可以读取函数内部的局部变量,且不会被垃圾回收机制回收,可以长期保存。

闭包的作用?

  1. 在函数外部可以访问函数内部的局部变量。
  2. 可以使函数内部的变量在函数执行结束之后不被销毁 ,长久保存在内存中,不会被垃圾回收机制回收。
  3. 使用闭包,可以封装自己的函数代码,实现模块化。
  4. 保护:避免命名冲突。
  5. 保存:解决循环绑定引发的索引问题。

闭包的缺点?

由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。如何解决:在销毁函数之前,将不使用的局部变量全部删除。

闭包的应用?

  1. 能够模仿块级作用域。
  2. 设计模式中的单例模式。
  3. for 循环中的保留 i 的操作。
  4. 防抖和节流。
  5. 函数柯里化。
  6. 在构造函数中定义特权方法。
  7. Vue 中数据响应式 Observer 中使用闭包。

8、什么是原型链?⭐⭐⭐

  • 每个函数身上都有一个 prototype 的原型对象,并且有一个__proto__的指针指向下一级原型对象,如果一个对象的属性或方法在自身中找不到,那么就会去 prototype 原型对象中查找,如果还找不到继续向上查找直到 null,当_proto_指针指向 null 时形成一个链条,这个链条叫做原型链。
  • 在原型链中,对象可以继承原型对象的属性和方法。如果想在构造函数中添加属性和方法,可以将它们添加到构造函数的 prototype 属性中,这样通过该构造函数创建的对象都可以访问到这些属性和方法。
  • 原型链的特点是:对象可以沿着原型链向上查找属性和方法,实现了属性和方法的共享和继承。

9、JS继承的方法有哪些?优缺点?⭐

JS继承的方法有以下几种:原型链继承、构造函数继承、组合继承、原型式继承和寄生式继承,寄生组合式继承,ES6 Class实现继承。继承的目的是:重复利用另外一个对象的属性和方法。

  • 原型链继承:将父类的实例作为子类的原型,从而实现对父类属性和方法的继承。优点:写法方便简洁,容易理解。缺点:不能传递参数和共享所有继承的属性和方法,当一个发生改变另外一个随之改变。

  • 构造函数继承:在子类的构造函数中调用父类的构造函数,使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上,从而实现对父类实例属性的继承。优点:解决了原型链继承不能传参的问题和父类的原型共享的问题。缺点:方法都在构造函数中定义,因此无法实现函数复用。

  • 组合继承:将原型链继承和构造函数继承结合起来,既可以实现对父类原型属性和方法的继承,又可以实现对父类实例属性的继承。优点: 解决了原型链继承和构造函数继承造成的影响。缺点: 无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

  • 原型式继承:通过创建一个临时构造函数来实现对父类的属性和方法的继承。优点:不需要单独创建构造函数。缺点:属性中包含的引用值始终会在相关对象间共享。

  • 寄生式继承:在原型式继承的基础上,通过在临时构造函数中添加方法和属性,从而实现对父类的继承。优点:写法简单,不需要单独创建构造函数。缺点:通过寄生式继承给对象添加函数会导致函数难以重用。

  • 寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。优点:高效率只调用一次父构造函数,并且因此避免了在子原型上面创建不必要,多余的属性。与此同时,原型链还能保持不变。缺点:代码复杂。

  • ES6 Class实现继承:ES5 的继承,实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面 (Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法加到 this 上面 (所以必须先调用super方法),然后再用子类的构造函数修改 this。需要注意的是,class 关键字只是原型的语法糖,JS继承仍然是基于原型实现的。 优点:语法简单易懂,操作更方便。缺点:并不是所有的浏览器都支持 class 关键字 lass Person。

10、new操作符具体都干了什么?⭐⭐

  1. 创建一个新对象 obj。
  2. 将该对象与构造函数通过原型链连接起来(设置该对象的构造函数)。
  3. 将构造函数中的 this 绑定到该对象上。
  4. 根据构建函数返回类型作判断,如果是值类型则返回新对象 obj,如果返回对象,则返回构造函数里的对象。
// 手写 new 操作符
function mockNew(constructor, ...args) {
    // 1.创建一个新对象 obj
    const obj = {};
    // 2.把构造函数当参数传入,新对象指向构造函数原型对象
    obj.__proto__ = constructor.prototype;
    // 3.通过 apply 将构建函数的 this 指向新对象
    let result = constructor.apply(obj, args);
    // 4.根据返回值判断
    return result instanceof Object ? result : obj;
}

11、JS的几种具体异常类型(报错)

  • SyntaxError:语法错误
  • ReferenceError:引用错误
  • RangeError:范围错误
  • ypeError:类型错误
  • URLError:与 url 相关参数不正确
  • EvalError:全局函数 eval 执行错误

12、什么是事件冒泡?什么是事件委托?

  • 事件冒泡:在一个对象上触发某类事件,这个事件会向这个对象的的父级传播,从里到外,直至它被处理或者到达了对象层次的最顶层,即 document 对象。这个过程就是事件冒泡。
  • 事件委托:事件委托就是利用事件冒泡,指定一个事件处理程序,就可以管理某一类型的所有事件。原理:在元素的父级元素添加事件,点击元素时,因为事件冒泡的作用实现事件委托。简单来说,事件委托就是将子元素的事件通过冒泡的形式交由父元素来执行。优点:使用事件委托可以减少代码执行优化资源。 

13、事件对象? 

  • event:事件对象。
  • currentTarget:绑定的事件。
  • target:触发的事件。
  • eventPhase:返回当前触发的阶段(捕获阶段1,事件派发阶段2,冒泡阶段3)
  • type:返回当前event对象的事件名。

14、undefined 和 null 区别?⭐

  1. undefind 是全局对象的一个属性,当一个变量没有被赋值或者一个函数没有返回值或者某个对象不存在某个属性却去访问或者函数定义了形参但没有传递实参,这时候都是 undefined ,undefined 通过 typeof 判断类型是 undefined。
  2. null 代表空值,代表一个空对象指针,代表对象的值未设置,相当于一个对象没有设置指针地址就是 null。null 通过 typeof 判断类型是 object。
  3. undefined 表示一个变量初始状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。当需要释放一个对象时,直接赋值为 null 即可,对象被赋值了null 以后,对象对应的堆内存中的值就是游离状态了,GC 会择机回收该值并释放内存。因此,需要释放某个对象,就将变量设置为 null,即表示该对象已经被清空,目前无效状态。
  4. null 是 javascript 的关键字,和其它语言一样都是代表空值, undefined 却是 javascript 才有的。是为了区分空指针对象和未初始化的变量,它是一个预定义的全局变量。

15、说一说伪数组和数组的区别?

  1. 伪数组它的类型不是 Array,而是 Object,而数组类型是 Array。
  2. 伪数组可以使用的 length 属性查看长度,也可以使用 index 获取某个元素,但是不能使用数组的其他方法,也不能改变长度,遍历使用 for in 方法。
  3. 伪数组转换成真数组方法:(1)Array.prototype.slice.call(伪数组) 、(2)[].slice.call(伪数组) (3)Array.from(伪数组),转换后的数组长度由 length 属性决定,索引不连续时转换结果是连续的,会自动补位。

16、对于数组去重都有哪些方法?⭐⭐ 

  1. 双重 for 循环:这是一个最笨的方法。
  2. 对象属性 key:利用对象属性名 key 不可以重复这一特点,如果对象中不存在,就 push 进空数组。
  3. for 循环 + indexOf:主要是利用 indexOf 的特性,查找元素返回下标,找不到就返回-1。-1就 push 进空数组。
  4. for 循环 + sort 排序:利用数组的 sort 排序方法去重,如果第 i 项 和 i-1 项不一致,就 push 进空数组。
  5. filter + indexOf:利用 filter 过滤配合 indexOf 查找元素,判断返回元素下标和过滤数组的 index 是否相等。
  6. Set:Es6 中新增了数据类型 Set,Set 的最大一个特点就是数据不重复,可以用作数组去重。new Set 方法,返回是一个类数组,需要结合扩展运算符...,转成真实数组。
  7. set + Array.from:Set 去重结合 Array.from 转成真实数组。Array.from(new Set(原数组))
  8. for 循环 + includes:includes 用来判断一个数组是否包含一个指定的值,是就返回 true,否则返回 false。判断空数组是否包含原数组的某个元素,不包含就 push 进空数组。
  9. reduce + includes:利用 reduce 遍历结合 includes去重。

17、 对join、push、split、splic、slice的理解?

  1. join:把数组变成字符串。
  2. split:把字符串变成数组。
  3. push:往数组最后一位添加成员。
  4. splice:增加、修改、删除数组的成员。
  5. slice:截取数组,然后返回一个新数组。

18、说一下this指向?⭐⭐ 

  • 全局作用域:无论是否在严格模式下,this 指向 window 对象。严格模式下全局作用域中函数中的 this 等于 undefined。不是严格模式时,全局作用域中函数中的 this 指向 window。
  • 对象中的函数:对象的函数中的 this 指向调用函数的对象实例。谁调用函数 this,this 就指向谁。
  • 事件处理函数:在事件处理函数中,this 指向触发事件的目标对象。

  • 构造函数:构造函数中的 this 指向构造函数创建的对象实例。
  • 箭头函数:this 对应定义时所在的对象,也就是上一级作用域中的 this。箭头函数的 this 不会被改变。
  • 嵌套函数:嵌套函数中的 this 不会继承外层函数的 this 值。
  • new:由 new 调用的话,this 指向新创建的对象。
  • call、apply、bind:由 call、apply、bind 调用,this 指向指定的对象。
  • 定时器:定时器中的 this,指向的是 window。

19、 js中call、apply、bind有什么区别?⭐⭐

  1. call、apply、bind 都是用来改变 this 指针指向。
  2. bind 只接收一个参数,就是 this 指向的执行上文。 call、apply 接收多个参数,第一个参数都是 this 指向的执行上文,后面的参数都是作为改变 this 指向的函数的参数。
  3. call 和 bind 是选项式参数,apply 是数组式参数。
  4. call 和 apply 都是立即执行,bind 返回的是一个改变执行上下文的函数,不会立即执行,可稍后调用。
  5. 应用场景:call 用于对象的继承 、伪数组转换成真数组。apply 用于找出数组中的最大值和最小值以及数组合并。bind 用于 vue 或者 react 框架中改变函数的 this 指向。

20、箭头函数和普通函数有什么区别?⭐⭐ 

  1. 普通函数的 this 指针指向调用者,可以修改。
  2. 箭头函数没有自己的 this,它的 this 是继承而来,默认指向在定义它时所处的对象 (父级作用域),不能修改。

21、JQ对象和DOM元素之间如何转换? 

  • DOM转JQ对象:$(DOM对象) 或 $("div")。
  • JQ对象转DOM:可以通过[index] 或者 .get(index)方法,例如 $("div")[0] 或者 $("div").get(1)。

22、JS模块化有哪些?

 commonjs、es6、amd、cmd

23、如何操作DOM元素?

原生操作DOM元素:

  • 直接给相应的元素加 id ,然后再 document.getElementById("id") 获取。

vue操作DOM元素:

  • 获取/操作根元素 DOM:$root。
  • 获取/操作父元素 DOM:$parent。
  • 获取/操作子元素 DOM: $refs $children。
  • 使用 ref,给相应的元素加 ref=“name” 然后再 this.$refs.name 获取到该元素。

24、防抖与节流的区别,并分别用代码表示 

  • 防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。作用:防止事件连续或高频触发,让它只触发一次或者最后一次。
  • 节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。作用:降低事件触发的频率,比如1s内最多执行一次。
  • 区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行一次。
    //防抖和节流函数都是用于防止事件高频率的重复触发
    //防抖: 在一定时间内,如果方法没用再次被触发,则执行最后一次
    <body>
        <button>点我</button>
        <script>
            var btn = document.querySelector("button");
            var tiemr = null;
            btn.onclick = function () {
                clearInterval(tiemr);
                tiemr = setTimeout(() => {
                    console.log("我触发了")
                }, 500)
            }
        </script>
    </body>
    
    //节流:在规定时间内只只执行一次或数次
    <body>
    	<button>按钮</button>
    	<script>
    	    var btn = document.querySelector("button");
    		var jie = true;
    		btn.onclick = function() {
    			if(jie) {
    			    jie = flase;
    				console.log('发送了请求');
                    setTimeout(()=>{
    				    jie = true;
    				},2000)
    			}
    		}	
    	</script>
    </body>

24、数组迭代的方法有哪些? 

  1. for。
  2. for in:可以遍历对象, 首个行参是 key。
  3. for of:只能遍历数组,首个行参是 value:。
  4. forEach:for的增强版,特殊简化版,不支持在循环中添加删除操作。
  5. while :先判断后执行。
  6. do while:先执行后判断。
  7. some:所有返回值都为真则返回真,否则返回假。
  8. every:反之。

25、for循环和forEach有什么区别?

  1. for 循环的 return 是终止循环 forEach 是返回参数。
  2. for 循环实际上是可以使用 break 和 continue 去终止循环的,但是 forEach 不行。
  3. forEach 不支持在循环中添加删除操作。
  4. for 多数时候都可以使用,一般我们需要知道循环次数。而 forEach 更适合于集合对象的遍历和操作。

26、使用JQ和vue的区别?

JQ 是函数库,本质上还是操控 JS,只不过更简便了。vue 是 mvvm 框架,核心是双向数据绑定,

一般情况下不需要操控 DOM 元素,而是操控数据为主。

三、ES6 篇

1、ES6新增的内容有哪些?⭐⭐⭐

let、const、结构赋值、class 类、箭头函数、map、set、promise、async await(es7)、扩展运算符...、Module 模块化。

2、ES6中,Set和Map的区别?⭐⭐⭐

set:ES6 提供新的数据结构 set,它类似于数组,成员的值都是唯一的,没有重复的值,可以用来做数组去重,但 set 是伪数组需要通过扩展运算符...转换成数组。set 不存储 value,内部的元素可以遍历, for...of...。

 实例操作方法: size、add、delete、has、clear。

  • size:返回 set 实例的成员总数。
  • add(value):添加某个值,返回 set 结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为 set 的成员。
  • clear():清除所有成员,没有返回值。

Map:"键值对"的数据结构, 数组重组。JavaScript 对象 object 本质上是键值对的集合,缺陷是只能使用字符串作为键,而 map 结构优化了这个缺陷,它提供了 "值-值" 对的形式,让键名不再局限于字符串,是一种更完整的 Hash 结构实现。简单来说:Map 类似于对象,也是键值对的集合,但是 "键" 的范围不限于字符串, 各种类型的值(包括对象)都可以当作键。遍历方法:keys( )、values( )、entries( )、forEach( )。 注意:由于一个 key 只能对应一个 value,所以多次对一个 key 放入 value,后面的值会把前面的值冲掉。

 实例操作方法:size、set、get、has、delete、clear。

  • size:返回 Map 实例的成员总数。
  • set:添加新的 key-value。
  • get:传入一个 key 返回一个 val。
  • delete:传入一个 key,删除这个 key-value。
  • has:查看是否有这个 key。
  • clear:清除所有成员,没有返回值。

Set 和 Map 的区别:

  1. Map 保存键值对,任何值都可以作为键值的值。Set 保存的是类数组数据,是值的集合。
  2. Map 有 get 和 set 方法,而 Set 有 add 方法但没有类似于 get 返回成员值的方法。
  3. Map 以键值对的形式存储,是一组映射关系。Set 只有值,并且 Set 中元素不可以重复且自动排序。
  4. Map 遍历方法有 keys( )、values( )、entries( )、forEach( )。Set 只有 for...of...。

3、map和forEach的区别?

  • map:map 有返回值,可以开辟新空间,return 出来一个 length 和原数组一致的数组,即便数组元素是 undefined 或者是 null,map 能新增删除元素。
  • forEach 默认无返回值,返回结果为 undefined,可以通过在函数体内部使用索引修改数组元素,forEach 不能新增删除元素。

4、es6 中的箭头函数?⭐⭐⭐

  1. 箭头函数相当于匿名函数,简化了函数定义。
  2. 箭头函数有两种写法,当函数体是单条语句的时候可以省略 {} 和 return,另一种是包含多条语句,不可以省略 {} 和 return。
  3. 箭头函数最大的特点就是没有自己的 this,它的 this 是从外部获取,就是继承外部的执行上下文中的 this。
  4. 由于没有 this 关键字所以箭头函数也不能作为构造函数。
  5. 箭头函数也没有原型和 super。
  6. 不能使用 yield 关键字,因此箭头函数不能用作 Generator 函数。
  7. 适用场景:简单的函数表达式,内部没有 this 引用,没有递归、事件绑定、解绑定,适用于 map、filter 等方法中。

5、什么是扩展运算符,用于什么场景?⭐⭐

  1. 扩展运算符(…) 是一个展开语法,可以在函数调用/数组构造时, 将数组表达式或者 string 在语法层面展开。还可以在构造字面量对象时, 将对象表达式按 key-value 的方式展开。展开的内容可以放在任何它可以存在的地方 (数组,函数,对象) 。
  2. 对象扩展运算符:对象的扩展运算符用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中,实际上等价于 Object.assign 合并对象,如果有同名属性,扩展运算符内部的同名属性会被覆盖掉,返回一个新对象。扩展运算符对对象实例的拷贝属于浅拷贝。
  3. 数组扩展运算符:在函数调用时将一个数组转为用逗号分隔的参数序列(将数组拆开成多个参数传递), 且每次只能展开一层数组。数组拷贝[...arr],如果数组里面对象是基础数据类型,则要将所有基础数据类型重新拷贝到新的数组中。合并数组。扩展运算符与解构赋值结合, 用于生成数组。将伪数组转为真正的数组。使用 Math 函数获取数组中特定的值,比如求一个数组的最大数简化 Math.max(...[14, 3, 77]),相当于 es5 的 apply,Math.max.apply(null, [14, 3, 77])。数组去重 [...new Set(arr)]。 往数组里 push 多个元素。扩展运算符后面可以放表达式。做为函数传递参数时不确定形参个数的时候使用。

6、JS变量提升?⭐⭐

变量提升是指 JS 的变量和函数声明会在代码编译期,提升到代码的最前面。 变量提升成立的前提是使用 Var 关键字进行声明的变量,并且变量提升的时候只有声明被提升,赋值并不会被提升,同时函数的声明提升会比变量的提升优先。

7、怎么实现Module模块化?

  1. 模块的功能主要由 export(导出) 和 import(导入) 组成。
  2. 每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口通过 import 来引用其它模块提供的接口。
  3. 同时还为模块创造了命名空间,防止函数的命名冲突。

8、同步和异步的区别?同步函数和异步函数的区别?⭐

  • 同步就是同时执行,异步就是分开来执行。
  • 同步函数就是把同步变成异步执行,异步函数就是把异步变成同步执行。
  • 场景:同步和异步的问题通常是指 ajax 的回调问题。如果是同步调用,在发起请求的时候就会暂停,等到服务器响应后继续运行。如果是异步调用,发起请求后不会暂停,立即执行后面的代码,服务器响应后会自动触发回调函数进行处理。异步的性能佳,同步则用于需要立即获取结果并实时处理的情况。

9、JS的执行顺序?同步任务和异步任务?⭐⭐⭐

js 是单线程语言,同一个时间只能做一件事,这样很容易造成阻塞,所以把任务分成了同步任务和异步任务两种。当主线程遇到异步任务,比如说计时器或者 ajax 请求回调问题,就把异步任务放进 "任务队列" 里,执行完同步任务后,再循环的去检查任务队列里面有哪些异步任务要执行。这是一个异步执行,分开来执行的,如果想要变成同步执行,比如说等到计时器执行完后再执行或者等请求服务器响应后再继续运行,可以使用回调函数,或者使用异步函数 promise 或 async await,把异步变成同步执行。所有异步任务都是在同步任务执行结束之后,从任务队列中依次取出执行。

JS实现异步的方法:

  1. 回调函数:回调函数是异步操作最基本的方法,优点是简单,容易理解和实现,缺点是不利于代码的阅读和维护,有回调地狱问题 (多个回调函数嵌套的情况)。
  2. promise:为了解决回调地狱和代码不规范问题,es6 出了个 promise ,promise 是一个异步函数,是异步编程的一种解决和优化的方案,在异步操作成功时通过状态调用 resolve 或 reject 并把结果作为参数传递出去,通过 then 接收到对应的数据,做出相应的处理。相比回调函数 promise 不仅能捕捉错误,还能解决回调地狱问题,通过多个 promise 调用 then 方法来把地狱回调转化为链式编程。缺点是错误需要通过回调函数捕获,只能异步的处理错误,Promise 链式调用相当于一个新的回调地狱。
  3. async/await:async/await 是基于 Promise 实现的,async/await 使异步代码看起来像同步代码。优点是使用方法清晰明了,更加优雅,可读性强,可以以通过 try-catch 捕捉错误,同步的处理错误,且 async/await 完美解决了回调地狱的问题。缺点是 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低,代码没有依赖性的话,完全可以使用 Promise 去实现。

10、 promise和async await区别?⭐⭐⭐ 

什么是 promise ? 为什么要有 promise ?

promise 是 es6 中的一个内置对象,实际是一个构造函数,是一个异步函数,是异步编程的一种解决方案,把异步执行变成同步执行。比传统的解决方案 “回调函数” 更加合理强大,解决了 “回调函数” 中的回调地狱,代码不规范,可读性低,不便维护等问题。(通过多个 promise 调用 then 方法来把地狱回调转化为链式编程)

promise 有什么作用?

 通常用来解决异步调用问题。解决多层回调嵌套的方案。提高代码可读性,更便于维护。

promise 写法?如何实现的?

可以使用 promise 构造函数 new 一个实例,promise 构造函数接收一个函数作为参数,这个函数有两个参数, 分别是成功回调 resolve 和失败回调 reject。在异步操作成功时调用 resolve,把 promise的状态从 pending 转变到 resolved,并将异步操作的结果作为参数传递出去。在异步操作失败时调用 reject,把 Promise 的状态从从 pending 变为 rejected,并将异步操作报出的错误,作为参数传递出去。Promise 实例生成后,当 promise 状态一改变,不管是成功还是失败,就都会来到 promise 对象的 .then 方法,根据其状态,选择特定的响应函数执行。then 方法返回的是一个新的 Promise 实例,因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法,把回调地狱转为链式编程。如果 Promise 的状态变为 reject 时,会被 catch 捕捉到,所以就把成功的处理逻辑写在 .then()里,把失败的处理逻辑写在 .cache() 里。

什么是 async await ?

async await 是 ES7 新特性,也是一个异步函数,把异步执行变同步执行,它是基于 promise 实现的,是一个语法糖。

async await 写法?

async await 基于 promise 实现的,async 写在方法前面,用于声明一个 function 是异步的,async 和 await 是配对使用的,await 只能写在 async 的内部,await 后面跟着的是一个 promise 对象,async 执行期间一旦遇到 await,会等后面的 Promise(异步)执行完毕再执行后面的代码,如果是 reject 状态,可以使用 try-catch 捕捉

promise 和 async await 区别:

相同点:promise 和 async await 都是优化异步编程的解决方案。

不同点:

  1. promise 是 ES6 的一个内置对象,是应用层的解决方案,通过 catch 来捕捉,只能异步的处理错误。async/await 是 ES7 的新特性,是基于 promise 的,可以说是 promise 的补充,是语言层的解决方案,可以让用户像编写同步代码一样编写异步代码,可以通过 try-catch 捕捉错误,同步的处理错误。
  2. promise 更多应用在函数封装中,async/await 用在函数的使用中。
  3. Promise 链式调用相当于一个新的回调地狱, 也不能统一处理异常。async/await 完美解决了回调地狱的问题。
  4. async/await 相对于 promise 来讲,写法更加优雅。async/await 用同步的写法使得可读性更强,同时方便 try-catch 捕获异常。

四、TS 篇

五、VUE 篇

六、uni-app 篇

七、HTTP 请求篇

八、git 篇

九、其他模块

十、手撕代码

猜你喜欢

转载自blog.csdn.net/Monsters___/article/details/132953264