ES6常用知识总结

123 阅读13分钟

1、var、let、const之间的区别

  1. 变量提升:const和let不存在变量提升情况;var存在变量提升情况。
  2. 暂时性死区:let, const存在暂时性死区 (只有等到声明变量的那一行代码出现,才可以获取和使用该变量);var由于有变量提升,所以不存在这种情况。
  3. 块级作用域:let, const存在块级作用域;var只有函数作用域和全局作用域。
  4. 重复声明:const、let不可以重复声明变量;var 可以重复声明(指的是同一作用域下重复声明)。
  5. 修改声明的变量:var、 let 可以修改变量(指的是修改变量指向的内存地址,简单类型就是变量本身),const不能修改变量。
  • 另外能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

2、箭头函数,跟普通函数的区别

箭头函数的特点:

  1. 使用“箭头”(=>)定义函数
  2. 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
  3. 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回
  4. 不可以使用new关键字创建实例对象
  5. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,且不可以修改this的值
  6. 不可以当作构造函数,也就是说,不可以使用new命令,原因是没有构造器constructor
  7. 不可以使用arguments对象,该对象在函数体内不存在
  8. 不可以使用yield命令,因此箭头函数不能用作 Generator 函数

image.png

3、ES6对数组新增了哪些扩展

1. 关于构造函数:

  • Array.from()将两类对象转为真正的数组:类似数组的对象和可遍历(iterable)的对象(包括 ES6 新增的数据结构 SetMap
  • Array.of()用于将一组值,转换为数组。没有参数的时候,返回一个空数组;当参数只有一个的时候,实际上是指定数组的长度;参数个数不少于 2 个时,才会返回由参数组成的新数组。

2. 实例对象新增的方法:

  • find()用于找出第一个符合条件的数组成员
  • findIndex返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
  • findLast用于找出最后一个符合条件的数组成员
  • findLastIndex返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
  • fill()使用给定值,填充一个数组,还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置
  • keys()是对键名的遍历
  • values()是对键值的遍历
  • entries()是对键值对的遍历
  • includes()用于判断数组是否包含给定的值(可以判断NaN)
  • flat()将数组扁平化处理,返回一个新数组,对原数据没有影响

3. 数组的空位:

  • ES6 则是明确将空位转为undefined

4. 排序稳定性:

  • sort()默认设置为稳定的排序算法,指的是排序关键字相同的项目,排序前后的顺序不变。

4、ES6对对象新增了哪些扩展?

1. 属性的简写:

  • 当对象键名与对应值名相等的时候,可以进行简写;方法也能简写,不过简写的对象方法不能用作构造函数,否则会报错

2. super关键字

  • 新增了另一个类似的关键字super,指向当前对象的原型对象

3. 属性的遍历

  • 一共有 6 种方法可以遍历对象的属性:for...in、Object.keys(obj)、Object.getOwnPropertyNames(obj)、Object.getOwnPropertySymbols(obj)、Reflect.ownKeys(obj)

4. 对象新增的方法

  • Object.is()严格判断两个值是否相等,与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身
  • Object.assign()方法用于对象的合并,将源对象source的所有可枚举属性,复制到目标对象target,方法的第一个参数是目标对象,后面的参数都是源对象
  • Object.keys()返回自身的(不含继承的)所有可遍历(enumerable)属性的键名的数组
  • Object.values()返回自身的(不含继承的)所有可遍历(enumerable)属性的值的数组
  • Object.entries()返回一个对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对的数组
  • Object.fromEntries()用于将一个键值对数组转为对象

5. 属性名表达式

  • 允许字面量定义对象时,将表达式放在括号内,表达式还可以用于定义方法名

5、对ES6新增Set、Map两种数据结构的理解

Set

  1. Set:类似于数组,但是成员的值都是唯一的,没有重复的值,我们一般称为集合。Set本身是一个构造函数,用来生成 Set 数据结构。
  2. Set 实例的属性和方法
  • add()添加某个值,返回 Set结构本身,当添加实例中已经存在的元素,set不会进行处理添加
  • delete() 删除某个值,返回一个布尔值,表示删除是否成功
  • has()返回一个布尔值,判断该值是否为Set的成员
  • clear()清除所有成员,没有返回值
  • size返回set的长度
  1. 遍历操作
  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员

Map

  1. Map类型是键值对的有序列表,而键和值都可以是任意类型。Map本身是一个构造函数,用来生成 Map数据结构
  2. Map实例的属性和方法
  • size 属性:
  • set():
  • get():
  • has():
  • delete():
  • clear():
  1. 遍历操作、
  • keys():返回键名的遍历器

  • values():返回键值的遍历器

  • entries():返回所有成员的遍历器

  • forEach():遍历 Map 的所有成员

  • 共同点:集合、字典都可以存储不重复的值;本身是一个构造函数共同遍历方法

6、ES6中模块化

是能够单独命名并独立地完成一定功能的程序语句的集合

1. 特点

  • 1、ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
  • 2、ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
  • 3、“编译时加载”或者称为静态加载,使得静态分析成为可能,比如引入宏(macro)和类型检验(type system)
  • 4、将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。
  • 5、ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict"
  • 6、一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
  • 7、import命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口

2. Module的加载实现

  • 1、默认情况下:浏览器同步加载js脚本,即渲染引擎遇到script标签就会停下来,等执行完脚本再继续向下渲染,如果是外部脚本就要先下载
  • 2、异步加载:渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。有两种方式 defer或async属性, defer:“渲染完再执行”,async:“下载完就执行”。
  • 3、es6模块加载:type="module" 浏览器是异步加载模块的,等同于type="defer"

3. ES6 模块与 CommonJS 模块的差异

  • 1、CommonJS 模块输出的是一个值的拷贝(一旦输出这个值,模块内部的变化就影响不到它),ES6 模块输出的是值的引用。
  • 2、CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • 3、CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
  • 4、CommonJS 模块的顶层this指向当前模块,ES6 模块之中顶层的this指向undefined

4. 循环加载

“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本

7、ES6中Promise及使用场景?

Promise对象是一个构造函数,用来生成Promise实例 Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject 当开发有异步操作时,就可以给异步操作包装一个promise

异步操作后会有三种状态:

  • Pending:初始状态/等待状态,比如正在执行网络请求,或者定时器没有到时间
  • fulfilled:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
  • Rejected:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
  • 对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态 一旦状态改变(从pending变为fulfilled和从pending变为rejected),就不会再变,任何时候都可以得到这个结果。 流程图:static.vue-js.com/1b02ae90-58…

Promise构建出来的实例存在以下方法:

  • then()  成功时执行
  • catch()  失败时执行
  • finally()  无论如何都会执行

构造函数方法

  • all():同样是将多个 Promise 实例,包装成一个新的 Promise 实例。全部状态是fulfilled才会返回fulfilled
  • race():同样是将多个 Promise 实例,包装成一个新的 Promise 实例。有一个实例率先改变状态,p的状态就跟着改变
  • allSettled():
  • resolve(): 参数可以分成四种情况,分别如下: 参数是一个 Promise 实例,promise.resolve将不做任何修改、原封不动地返回这个实例 参数是一个thenable对象,promise.resolve会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then()方法 参数不是具有then()方法的对象,或根本就不是对象,Promise.resolve()会返回一个新的 Promise 对象,状态为resolved 没有参数时,直接返回一个resolved状态的 Promise 对象
  • reject():方法也会返回一个新的 Promise 实例,该实例的状态为rejected
  • try()

使用场景

  1. 将图片的加载写成一个Promise,一旦加载完成,Promise的状态就发生变化
  2. 过链式操作,将多个渲染数据分别给个then,让其各司其职。或当下个异步请求依赖上个请求结果的时候,我们也能够通过链式操作友好解决问题
  3. 通过all()实现多个请求合并在一起,汇总所有请求结果,只需设置一个loading即可
  4. 通过race可以设置图片请求超时

8、ES6中的Generator及使用场景?

ES6 提供的一种异步编程解决方案。遍历器对象,可以依次遍历 Generator 函数内部的每一个状。形式上,Generator 函数是一个普通函数,但是有两个特征:

  • function关键字与函数名之间有一个星号
  • 函数体内部使用yield表达式,定义不同的内部状态

运行逻辑如下

  1. 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。返回的对象中value对应状态值, done用来判断是否存在下个状态
  2. 通过next方法才会遍历到下一个内部状态。下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。通过调用next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值
  3. 如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
  4. 如果该函数没有return语句,则返回的对象的value属性值为undefined

使用场景

  1. 异步解决方案
  • 回调函数
  • Promise 对象
  • generator 函数
  • async/await
  1. 区别
  • promiseasync/await是专门用于处理异步操作的
  • Generator并不是为异步而设计出来的,它还有其他功能(对象迭代、控制输出、部署Interator接口)
  • promise编写代码相比Generatorasync更为复杂化,且可读性也稍差
  • Generatorasync需要与promise对象搭配处理异步情况
  • async实质是Generator的语法糖,相当于会自动执行Generator函数
  • async使用上更为简洁,将异步代码以同步的形式进行编写,是处理异步编程的最终方案

9、ES6中Proxy的及使用场景?

Proxy为 构造函数,用来生成 Proxy 实例。 target表示所要拦截的目标对象(任何类型的对象,包括原生数组,函数,甚至另一个代理) handler通常以函数作为属性的对象,用来定制拦截行为

proxy实例方法

Proxy 支持的拦截操作一共有 13 种。

  1. get()
  • 拦截读取操作,可以接受三个参数。依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
  • 如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性,否则会报错
  1. set()
  • 拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
  • 如果目标对象自身的某个属性,不可写且不可配置,那么set方法将不起作用

使用场景

Proxy其功能非常类似于设计模式中的代理模式,常用功能如下:

  • 拦截和监视外部对对象的访问
  • 降低函数或类的复杂度
  • 在复杂操作前对操作进行校验或对所需资源进行管理

reflect

  • 1、将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上
  • 2、修改某些Object方法的返回结果,让其变得更合理
  • 3、让Object操作都变成函数行为。
  • 4、Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
  • 也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
  • Reflect对象一共有 13 个静态方法。

参考文献:es6.ruanyifeng.com/#docs/intro