ES6 前端面试题总结
1. ES6新特性
- 新增声明命令let、const :
let
、const
都是块级作用域,以{}
代码块作为作用域范围,只能在代码块里面使用;- 不存在变量提升,只能先声明后使用,否则会报错,语法上称为 暂时性死区;
- 在同一代码块内,不允重复声明;
const
声明的是一个只读常量,在声明时就需要赋值;
- 模板字符串 :
- 用一对反引号表示,它可以当作普通字符串使用,也可以用来定义多行字符串,也可以在字符串中嵌入变量、JS表达式或函数,需要写在
${}
中;
- 用一对反引号表示,它可以当作普通字符串使用,也可以用来定义多行字符串,也可以在字符串中嵌入变量、JS表达式或函数,需要写在
- 函数的扩展 :
- 函数的默认参数:
- ES6为函数提供了默认值,在定义函数时便初始化了这个参数,以便在参数没有被传递进去时使用;
- 箭头函数;
- 函数的默认参数:
- 对象的扩展 :
- 属性简写;
Object.keys()
;Object.values()
;Object.assign()
;
- for-of循环;
- import 和 export :
export
用于对外输出本模块(一个文件可以理解为一个模块)变量的接口;import
用于在一个模块中加载另一个含有export
接口的模块;import
命令只能在模块的顶部,不能在代码块中;
- Promise 对象 :
Promise
是异步变编程的一种解决方案,将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,主要是为了解决异步处理回调地狱(也就是循环嵌套的问题)而产生的;Promise
构造函数包含一个参数和一个带有reaolve
(解析) 和reject
(拒绝)两个参数的回调函数,在回调中执行一些操作(例如异步),如果一切正常,则调用resolve()
,否则调用reject()
;- 对于已经实例化过的
Promise
对象可以调用Promise.then()
方法,传递resolve
和reject
方法作为回调; Promise.then()
方法接受两个参数:onResolve
和onReject
,分别代表当前Promise
对象在成功或失败时;
- 解构赋值;
- Set数据结构 :
- 类似数组,所有的数据都是唯一的,没有重复的值。它本身是一个构造函数;
Size()
:数据的长度;Add()
:添加某个值,返回Set结构本身;Delete()
:删除某个值,返回一个布尔值,表示删除是否成功;Has()
:查找某条数据,返回一个布尔值;Clear()
:清除所哟成员,没有返回值;
2. ES6的继承 和 ES5的继承有什么区别?
- ES5:
- 继承是通过原型或者构造函数机制来实现的;
- ES6:
- 用
calss
关键字定义类,里面有构造方法,类之间通过extends
关键字实现,子类必须在constructor
方法中调用super
方法;
- 用
3. var、let、const有什么区别
var
声明变量可以重复声明,而let
不可以重复声明;var
是不受限于块级的,而let
是受限于块级;var
会与window
相映射(会挂一个属性),而let
不与window
相映射;var
可以在声明之前访问,而let
有暂时性死区,在声明的上面访问变量会报错;const
声明之后必须赋值,否则会报错;const
定义不可变的量,改变了会报错;const
和let
一样不会与window
相映射,支持块作用域,在声明的之前访问变量会报错;
4. module、exort、import有什么作用
module、exort、import
是ES6用来统一前端模块化方案的设计思路和实现方案;export、import
的出现统一了前端模块化的实现方案,整合规范了浏览器/服务器的模块化方法,用来取代传统的AMD/CMD、requireJS、seaJS、commondJS
等等一系列前端模块的不同实现方案,使前端模块化更加统一规范,JS也能更加实现大型的应用程序开发;import
引入的模块是静态加载(编译阶段加载)而不是动态加载(运行时加载);import
和export
导出的接口值是动态绑定的,即通过接口,可以取到模块内部实时的值;
5. Set 和 Map 的区别?
- Set :
- Set对象允许存储任何类型的唯一值;
- Set是值得合集,集合中的元素只能出现一次,即集合中的元素是唯一的;
- 存放的是地址不同的引用数据类型和值不同的基本数据类型;
set.add()
:添加数据;set.clear()
:清空数据;set.delete()
:删除数据;set.has()
:查找数据;
- Map :
- Map对象是键值对的集合,Map中的一个键只能出现一次,它在Map的集合中是独一无二的;
- 本质上是键值对的集合;
- 读:
map.get()
; - 写:
map.set()
; - 清空:
map.clear()
; - 查:
map.has()
; - 删除:
map.delete()
;
- 区别 :
- 应用场景:
- Set用于数组去重;
- Map用于数据存储;
- Set:
- 成员不能重复;
- 只有键值没有键名,类似数组;
- 可以遍历;
- Map:
- 本质上是键值对的集合,类似集合;
- 可以遍历,可以跟各种数据格式转换;
- 应用场景:
6. setTimeout、Promise、async/await 的区别?
setTimeout
的回调函数放在 宏任务队列 中,等到执行栈清空以后执行;Promise.then()
里的回调函数会放到 相应宏任务的微任务队列 中,等宏任务里面的同步代码执行完毕再执行;async
函数表示函数里面可能会有异步方法,await
后面跟一个表达式;await
方法执行时,遇到await
会立即执行表达式,然后把表达式后面的代码放到微任务队列中,让出执行栈让同步代码先执行;
7. 介绍一下Promise
- Promise是解决异步编程导致的地狱回调问题(异步编程不方便);
- Promise是一个容器,里面保存着异步操作的结果;
- 从语法上来讲,Promise是一个对象,从他里面可以获取异步操作的结果;
- 特点 :
- Promise的状态不受外界的影响:
- Promise对象代表一个异步操作,有三种状态,pending、fulfilled、reject,只有异步操作的结果才可以决定Promise当前是哪一种状态,其他任何操作都无法改变这个状态;
- 一旦状态改变,就不会再变,任何时候都能获取异步操作的结果;
- Promise对象的状态改变,只有两种可能:pending->fulfilled 或 pending ->rejected。只有这两种情况发生,状态就不会再变了,会一直保持这个结果。如果改变已经发生,你再对Promise对象添加回调函数,也会立即得到这个结果
- Promise的状态不受外界的影响:
- 缺点 :
- Promise一旦创立,就会立即执行,无法中途取消;
- 如果不设置回调函数,Promise内部抛出的错误无法反应到外部;
- 当处于pending状态时,无法得到目前进展到哪一阶段;
8. Promise.all() 和 Promise.race() 的区别?
Promise.all()
:- 发起并行的Promise异步操作,等待所有的异步操作全部结束才会执行下一步操作;
- 等待机制;
- 注意:
- Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例;
Promise.race()
;- 发起并行的Promise异步操作,只要任何一个异步操作完成,就立即执行下一步操作;
- 赛跑机制;
all
和race
的入参都是数组;
9. Promise有几种状态,什么时候进入catch?
- 三种状态:
- pending ===> 进行中;
- fulfilled ===> 完成;
- reject ===> 失败;
- 当 状态为 rejected 时,会进入catch;
10. Promsie 中的 reject 和 catch 处理上有什么区别?
reject
用来抛出异常,catch
用来处理异常;reject
是Promsie
的方法,catch
是Promise
实例的方法;reject
后的东西一定会进入then
中的第二个回调,如果then
中没有第二个回调,则进入catch
;
4。 网络异常,会直接进入catch
而不会进入then
的第二个回调;
js
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从"未完成"变为"成功"(即从 pending 变为
resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从"未完成"变为"失败"(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
----------------------------------------------------------------------
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。这两个函数都是可选的,不一定要提供。它们都接受Promise对象传出的值作为参数
11. new Promise是同步还是异步
new Promise
的构造函数本身是同步执行的。- 当您创建一个新的Promise实例时,传递给Promise构造器的executor函数(即带有
resolve
和reject
参数的那个函数)会立即、同步地执行;
12. promise的then链是同步还是异步
- Promise的
then
方法返回的是一个新的Promise,并且其内部的回调函数是异步执行的。当Promise状态改变(即从pending变为fulfilled或rejected)时,与该状态改变关联的then
或catch
回调会作为一个微任务(microtask)添加到事件循环的任务队列中。 - 在JavaScript中,事件循环分为宏任务(macrotask)和微任务(microtask)两个队列,Promise的回调属于微任务队列。这意味着,在当前宏任务执行完毕(包括所有同步代码)后,但在 下一次宏任务开始前,会先清空微任务队列。因此,虽然
then
链看起来像是同步代码的一部分,但实际上它的回调会在稍后异步执行。
13. promise的then链为什么是异步的
Promise
的then
链式异步执行的,这是由于Promise
的设计目的和JavaScript
运行环境(特别是事件循环机制)决定的;- 微任务队列 :
- 当一个
Promise
被resolve
或reject
,并且then
方法中有回调函数需要执行时,这些回调函数不会立即执行,而是被放入到微任务队列中等待; - 这意味着它们会在当前脚本的所有同步代码执行完毕,以及当前宏任务(例如事件回调、定时器等)执行结束后,在下一个事件循环迭代时被执行;
- 当一个
- 异步流程控制 :
Promise
旨在提供一种更优雅的方式来管理异步操作的结果。如果then
回调同步执行,那么它将无法实现真正的异步处理,既无法在异步操作完成后再执行相关逻辑;
- 避免阻塞主线程 :
- 如果回调函数同步执行,可能导致后续的异步结果无法及时得到处理,从而阻塞了主线程;
- 通过将其置于微任务队列中,可以确保即便有大量
Promise
链式调用,也不会影响其他同步代码的执行及浏览器UI渲染;
- 一致性与可靠性 :
- 无论
Promise
的状态改变是因为同步还是异步操作引起的,其回调始终遵循相同的异步执行模型,这为开发者提供了一致的预期行为,增强了程序的可读性和稳定性;
- 无论
- 总的来说,
Promise
的then
链异步执行是为了适应并强化JavaScript
异步编程模式,保证不会阻塞主线程,并且能够以有序的方式处理异步操作的结果;
14. ES6 和 commonjs 模块化规范的区别
- CommonJS是同步加载,ES6是异步加载;
- CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用;
- CommonJS:一旦输出一个值,模块内部的变化就影响不到这个值;
- ES6:JS引擎对脚本静态解析的时候,遇到模块的加载命令import,就会生成一个只读引用,等到脚本真正执行的时候,再根据这个只读引用,到被加载的那个模块中取值;
- CommonJS模块是运行时加载,ES6模块是编译时输出接口:
- CommonJS加载的是一个对象,该对象只有在脚本运行完才会生成;
- ES6模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成;