一文总结 ES 新特性
一文总结 ES 新特性
总结并列出 ES 5 及之后的新特性
一、理解 ES
全称: ECMAScript (/ˈɛkməskrɪpt/)
它是一种由 ECMA 组织(前身为欧洲计算机制造商协会)制定和发布的脚本语言规范
我们学习的 JavaScript 就是 ECMA 的实现
JS 包含三个部分:
ECMAScript(JS 基础、核心部分)
扩展 → 浏览器端
BOM(浏览器对象模型)
DOM(文档对象模型)
扩展 → 服务器端
Node.js
ES 的几个重要版本
之前的为 ES 3(ES 4 夭折了,没发布)
ES 5:2009 年发布
ES 6(ES 2015):2015 年发布,也称为 ECMA 2015——重点(之后的 ES 就以年份命名)
ES 7(ES 2016):2016 年发布,也称为 ECMA 2016
二、ES 5 新特性
ES 5 对 JS 进行了修修补补,大概可以分为以下几类:
1、严格模式
理解:
运行模式分为正常(混杂)模式与严格模式
严格模式使得 JavaScript 在更严格的语法条件下运行
目的/作用:
使得 Javascript 在更严格的条件下运行
消除 Javascript 语法的一些不合理、不严谨之处,减少一些怪异行为
消除代码运行的一些不安全之处,保证代码运行的安全
使用:
将全局或函数的第一条语句定义为:
"use strict"如果浏览器不支持,只解析为一条简单的语句,没有任何副作用
语法和行为改变:
声明定义变量必须用
var(没有隐式的全局变量了,你要创建全局变量必须是显式的)禁止自定义的函数中的
this关键字指向全局对象(window或global),不管是fn()在全局调用还是apply()、call()默认都不会指向全局对象创建
eval作用域,更安全不准使用
witharguments只保存原始参数,对形参的赋值不会对arguments有影响,不准用arguments.caller和arguments.callee不支持八进制字面量,比如
var a = 015会报错对象字面量或函数形参中,如果有重复的键名就会报错
如果一个属性的
writeable是false,给这个属性赋值会报错如果一个属性的
configurable是false,则delete这个属性会报错
2、JSON 序列化和反序列化
作用: 用于在 JSON 字符串与 JS 对象/数组相互转换
JSON.stringify(obj/arr)JS 对象(数组)转换为 JSON 数据(字符串)JSON.parse(json)JSON 字符串转换为 JS 对象(数组)
3、Object 扩展
ES 5 给 Object 扩展了一些静态方法
Object.keys(),Object.create(),Object.defineProperty,Object.defineProperties,Object.getOwnPropertyDescriptor(),Object.getOwnPropertyNames(obj),Object.getPrototypeOf(obj)Object.seal(),Object.freeze(),Object.preventExtensions(),Object.isSealed(),Object.isFrozen(),Object.isExtensible()
常用的两个:
create
Object.create(prototype[, descriptors]):创建一个新的对象,返回值是新对象
作用:使用现有的对象来作为新创建对象的原型
为新的对象指定新的属性,并对属性进行描述
value:指定值writable:标识当前属性值是否是可修改的,默认为falseconfigurable:标识当前属性是否可以被删除,默认为falseenumerable:标识当前属性是否能用for in枚举,默认为false
defineProperties
Object.defineProperties(object, descriptors):为指定对象定义扩展多个属性
get 方法:用来得到当前属性值的回调函数
set 方法:用来监视当前属性值变化的回调函数
惰性求值:点击才给值(什么时候要什么时候给),会再次调用 get 方法

什么时候调用:
get 方法:获取扩展属性值的时候 get 方法自动调用
set 方法:监听
存储器属性:setter、getter 一个用来存值,一个用来取值
对象本身也有两个方法:
get propertyName(){}
set propertyName(){}
4、Array 扩展
Array.isArray(arr):判断一个对象 arr 是否是数组
Array.prototype.indexOf(value):得到值在数组中的第一个下标
Array.prototype.lastIndexOf(value):得到值在数组中的最后一个下标
Array.prototype.forEach(function(item, index, array){}[, asThis]):遍历数组,返回值是 undefined
Array.prototype.map(function(item, index, array){}[, asThis]):遍历数组返回一个新的数组(每一项是回调函数的返回值)
Array.prototype.filter(function(item, index, array){}[, asThis]):遍历过滤出一个子数组,返回一个由条件为 true 的元素组成的新数组
Array.prototype.reduce(function(accumulator, item, index, array)[, initValue]):Array.prototype.reduce 对数组中的每个元素按序执行一个提供的回调函数,每次执行回调函数会将之前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值
Array.prototype.reduceRight:从右到左
Array.prototype.some(function(){item, index, array}[, asThis]):数组中是否至少有一个元素符合回调函数给定的条件,有则返回 true,没有返回 false
Array.prototype.every(function(item, index, array){}[, asThis]):判断一个数组内的所有元素是否都能通过指定函数的测试,返回布尔值(回调函数有三个参数,第一个为当前遍历的对象、第二个为当前的下标、第三个为数组本身,方法还接受第二个参数,将作为 this)
5、Function 扩展
函数新增 bind 方法,Function.prototype.bind(asThis),将函数内的 this 绑定为 asThis,并将函数返回
强制绑定 this 使用 call/apply 和 bind
this的值通过函数调用的时候确定五种函数调用形式
fn,this是默认值,undefined或windowobj.x.fn(),this是前面调用的内容obj.x,例如btn.addEventListener里面this就是btncall(asThis, args)或apply(asThis, [args]),this就是传的asThisnew fn(args),this就是新创建的对象
🔖 面试题:区别
bind()与call()和apply()
fn.bind(asThis, args):指定函数中的 this,并返回函数(不会立即调用),一般用在回调函数绑定其他对象的 this
fn.call(asThis, args):指定函数中的 this,并调用函数
fn.apply(asThis, [args]):指定函数中的 this,并调用函数
总结:三个都可以给 fn 指定 this,bind 不会调用 fn,call 和 apply 都会调用 fn,call 的其他参数依次以逗号分隔,apply 的其他参数以数组形式传递
6、Date扩展
Date.now():得到当前时间值,之前new Date()Date.prototype.toISOString:新增方法,会返回一个 ISO 格式的字符串(YYYY-MM-DDTHH:mm:ss.sssZ)new Date(string)和Date.parse(string)新增对 ISO 格式的支持
7、其他
新增
String.prototype.trim,去除字串头尾空格尾逗号不报错,即多余的逗号不会报错,如
{a: 1, b: 2,}属性名可以使用关键字和保留字了,例如
{if: 1, else: 2}NaN、Infinity、undefined都是常量了,不可更改parseInt()第二个参数默认为 10/regexp/正则字面量每次都会产生一个新的对象
三、ES 6 新特性
ES 6 新增了很多特性,让 JS 变得非常好用
1、2 个声明变量的新关键字
ES 6 中新增了块作用域,{} 包裹的地方就是一个块,ES 5 中没有块级作用域(只有全局和函数作用域)
let 关键字
作用:与 var 相似,用于声明一个变量
特点:
在块作用域内有效
不能重复声明
不会预处理,不存在变量提升
应用:
循环遍历加监听
使用 let 代替 var 是趋势
const 关键字
作用:定义一个常量
特点
不能修改
其他特点同 let
应用
保存不用改变的数据
let 和 const 声明的变量都是有块级作用域的
let 和 const 声明变量在块作用域内都有暂时性死区,即在声明之前使用该变量会报错
2、变量(对象)的解构赋值
理解:
从对象或数组中提取数据,并赋值给多个变量
将包含多个数据的对象/数组一次赋值给多个变量
数据源:对象/数组
目标:{a, b}/[a, b]
对象的解构赋值:let {n, a} = {n:'tom', a:12} 把对象中的值赋值出来(根据属性名 key)
数组的解构赋值:let[a, b] = [1, 'luwang'] (根据下标)
用途:数组匹配、对象匹配、参数匹配(给多个形参赋值)
3、各种数据类型的扩展
(1) 字符串
模板字符串
作用:简化字符串的拼接
模板字符串必须用两个 "`" 包裹起来,ESC 下面那个键
变量的部分使用
${xxx}定义
字符串支持 Unicode
String.fromCodePointString.prototype.codePointAt
新增一些方法
String.prototype.includes(str):判断是否包含指定的字符串String.prototype.startsWith(str):判断是否以指定字符串开头String.prototype.endsWith(str):判断是否以指定字符串结尾String.prototype.repeat(count):重复指定次数
(2) 数值
二进制与八进制表示法:二进制用 0b,八进制用 0o
新增方法:
Number.EPSILON:最小精度Number.isFinite(i):判断是否是有限大的数字Number.isNaN(i):判断是否是NaNNumber.isInteger(i):判断是否是整数Number.isSafeInteger(i)Number.parseInt(str):将字符串转换为对应的数值Math.acosh、Math.hypot、Math.imul、Math.signMath.trunc(i):直接去除小数部分
(3) 对象
简化的对象写法(短语法)
省略同名的属性值
省略方法的 function
属性名支持表达式,需要用方括号括起来:
属性简写和解构赋值结合使用:
在函数的参数中使用对象的解构赋值,可以避免在函数体内部再次对参数对象进行解构赋值(
const {id, name} = user)函数的参数如果是一个对象的成员,可以使用对象简写方式(
{id: id, name: name}){data: res}等同于{data: data},data是一个变量,res是一个新的变量,可以用于解构赋值(获取到等号右边的data.data)
复制对象
Object.assign(target, source1, source2..):将源对象的属性复制到目标对象上
判断是否相等
Object.is(v1, v2):判断2个数据是否完全相等
__proto__ 属性
__proto__ 属性:隐式原型属性。ES 6 中能直接操作__proto__属性,但是不推荐使用
(4) 数组
Array.from(v):将伪数组对象或可遍历对象转换为真数组Array.of(v1, v2, v3):将一系列值转换成数组find(function(value, index, arr){return true}):找出第一个满足条件返回true的元素findIndex(function(value, index, arr){return true}):找出第一个满足条件返回 true 的元素下标fill:填充数组copyWithin:复制数组中一系列元素到同一数组指定的起始位置entries:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键/值对keys:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键values:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的值
(5) 函数
Ⅰ、箭头函数
让函数写法更简便
基本语法:
没有参数:
const fn = () => console.log('xxxx')箭头前的()不能省略一个参数:
i => i+2可以省略大于一个参数:
(i,j) => i+j()不能省略函数体不用大括号:默认返回结果
函数体如果有多个语句,需要用
{}包围
使用场景:多用来定义回调函数
特点:
简洁
箭头函数没有自己的
this,箭头函数的this不是调用的时候决定的,而是在定义的时候所处的对象就是它的this扩展理解:箭头函数的
this看外层是否有函数箭头外层有函数,
this是外层函数的this箭头外层无函数,
this是window
Ⅱ、参数处理
3 点运算符/点点点运算符
第一种用法:在函数中,rest(可变)参数
通过形参左侧的
...来表达,取代arguments的使用比
arguments灵活,只能是最后部分形参参数arguments是伪数组,有length,但是没有数组的一般方法,不能使用forEach遍历callee是arguments的一个属性,等于函数本身,递归的时候可以写为:arguments.callee()

第二种用法——扩展/展开运算符,可以分解出数组或对象中的数据
Ⅲ、形参的默认值
定义形参时指定其默认的值
当不传入参数的时候默认使用形参里的默认值
(6) 正则表达式
正则表达式字面量添加 Unicode 支持(
u标记)正则表达式添加
y标记,支持粘滞匹配
4、新增数据类型
(1) Symbol 类型
前言:ES 5 中对象的属性名都是字符串,容易造成重名,污染环境
概念:ES 6 中添加了一种原始数据类型 symbol(已有的数据类型:String、Number、boolean、null、undefined、对象)
特点:
Symbol 属性对应的值是唯一的,解决命名冲突问题
Symbol 值不能与其他数据进行计算,包括与字符串拼串
for in、for of 遍历时不会遍历 symbol 属性
使用:
调用 Symbol 函数得到 symbol 值
传参标识
内置 Symbol 值
除了定义自己使用的 Symbol 值以外,ES 6 还提供了 11 个内置的 Symbol 值(查看官方文档)
对象的 Symbol.iterator 属性,指向该对象的默认遍历器方法
(2) Set/Map 容器结构
容器: 能保存多个数据的对象,同时必须具备操作内部数据的方法
任意对象都可以作为容器使用,但有的对象不太适合作为容器使用(如函数)
Set 的特点:保存多个 value,value 是不重复 ====>数组元素去重
Map 的特点:保存多个 key-value,key 是不重复,value 是可以重复的
API:
Set 容器:无序不可重复的多个 value 的集合体
Set():创建一个空的 Set 容器Set(arr):创建一个 Set 容器,同时将 arr 数组(其中 arr 是一维数组)中的元素添加到 Set 容器中(去重)add(value):向 Set 容器中添加一个 valuedelete(value):删除 Set 容器中指定的 valueclear():清空 Set 容器中的所有元素has(value):判断 Set 容器中是否存在指定的 valuesize:获取 Set 容器中元素的个数
Map 容器:无序的 key、不重复的多个 key-value 的集合体
Map():创建一个空的 Map 容器Map(arr):创建一个 Map 容器,同时将 arr 数组(其中 arr 是二维数组)中的元素添加到 Map 容器中(去重)set(key, value):向 Map 容器中添加一对 key-valueget(key):获取 Map 容器中指定 key 对应的 valuedelete(key):删除 Map 容器中指定的 key-valueclear():清空 Map 容器中的所有元素has(key):判断 Map 容器中是否存在指定的 keysize:获取 Map 容器中元素的个数
(3)WeakSet 和 WeakMap 类型
(4)TypedArray 类型
一个 TypedArray 对象描述了底层二进制数据缓冲区的类数组视图
5、class 类
ES6 中新增的语法,用于实现面向对象编程
通过 class 关键字定义类,实现类的继承
(1) 之前实现继承
回顾:原型、构造函数、构造函数+原型——继承

(2) class 定义类
在类中通过 constructor() 定义构造方法(相当于构造函数)
类声明和类表达式的区别
类声明:类声明不可以省略类名,类名是标识符
类表达式:类表达式的类名是可选的,如果有类名,类名是标识符
constructor() 构造方法
通过 new 关键字调用类时,会自动调用 constructor() 构造方法
constructor() 构造方法是类中的默认方法,如果类中没有显式定义构造方法,那么类中会有一个隐式的、默认的空的 constructor() 构造方法
通过 constructor() 构造方法可以给实例对象添加属性

(3) class 类的继承
一般方法:xxx () {}
用 extends 来定义子类(实现类的继承)
用 super() 来调用父类的构造方法
子类方法自定义:将从父类中继承来的方法重新实现一遍(重写从父类继承的一般方法)
在一个构造方法中可以使用
super关键字来调用父类的构造方法在派生类中(子类),
super()必须要先调用,然后才能使用this关键字,否则会报错super关键字也可以用来调用父类的普通方法extends关键字用来实现类的继承,extends后面跟父类的名称(也可以是内建对象)
(4) class 类的静态方法
通过 static 关键字来定义静态方法
静态方法是通过类来调用的,不能通过实例对象来调用
静态方法中的 this 指向类本身
(5) class 类的 getter 和 setter 方法
通过 get 和 set 关键字来定义 getter 和 setter 方法
getter 和 setter 方法是通过实例对象来调用的
getter 和 setter 方法中的 this 指向实例对象
(6) class 类的静态属性
通过 static 关键字来定义静态属性
静态属性是通过类来调用的,不能通过实例对象来调用
静态属性中的 this 指向类本身
(7) 私有类字段(属性和方法)
私有类字段是指类中只能在类的内部访问的字段(属性和方法)
私有类字段可以通过在字段名前面添加
#来定义
6、Promise 对象
理解:
Promise 对象代表了某个将要发生的事件(通常是一个异步操作)
ES 6 的 Promise 是一个构造函数,用来生成 promise 实例
解决回调地狱(回调函数的层层嵌套,编码是不断向右扩展,阅读性很差);有了 promise 对象,可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数(回调地狱)
能以同步编码的方式实现异步调用
在 ES 6 之前原生的 JS 中是没这种实现的,一些第三方框架(jQuery)实现了 Promise
promise 对象的 3 个状态:
pending:待定状态
fullfilled:成功状态
rejected:失败状态
在同一个 Promise 中只能 pending 到 pending、pending 到 fullfilled、pending 到 rejected,不能成功之后又失败或失败之后在成功
应用:
使用 promise 实现超时处理
使用 promise 封装处理 Ajax 请求
(1) Promise 的基本使用
ES 6 中定义实现 API(使用 Promise 基本步骤):
例子:
例如:新闻、新闻的评论,只发新闻的内容;在接着根据新闻的 id 拿取这个新闻下的评论
new Promise()创建一个新的 Promise 对象参数:回调函数(函数中有两个参数,resolve、reject)
resolve()将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去reject()将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
创建的 Promise 对象可以调用一些方法
then():添加状态改变时的回调函数catch():添加状态改变时的回调函数finally():添加状态改变时的回调函数all():将多个 Promise 实例,包装成一个新的 Promise 实例race():将多个 Promise 实例,包装成一个新的 Promise 实例resolve():将现有对象转为 Promise 对象reject():返回一个新的 Promise 实例,该实例的状态为 rejected
(2) Promise 的链式调用
生成的 Promise 对象可以进行链式调用,即 then() 方法返回的是一个新的 Promise 对象,可以继续调用 then() 方法
7、Iterator 迭代器
概念:iterator 是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
为各种数据结构,提供一个统一的、简便的访问接口
使得数据机构的成员能够按照某种次序排列
ES 6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
工作原理
创建一个指针对象(遍历器对象),指向数据结构的起始位置
第一次调用
next方法,指针自动指向数据结构的第一个成员接下来不断调用
next方法,指针会一直往后移动,直到指向最后一个成员没调用
next方法返回的是一个包含 value 和 done 的对象{value: 当前成员的值, done: 布尔值}value 表示当前成员的值,done 对应的布尔值表示当前的数据的结构是否遍历结束
当遍历结束的时候返回的 value 值是 undefined,done 值为 false
原生具备 Iterator 接口的数据,可用 for...of 遍历
扩展理解
当数据结构上部署了 Symbol.iterator 接口,该数据就是可以用 for of 遍历
当使用 for of 去遍历目标数据的时候,该数据会自动去找 Symbol.iterator 属性(Symbol.iterator 属性指向对象的默认遍历器方法)
Array
arguments
set 容器
map 容器
String
……
for-of 循环:可以遍历任何容器(Set、Map)、数组、对象、伪/类对象、字符串、可迭代的对象
例如
8、Generator 生成器
概念:
ES 6 提供的解决异步编程的方案之一
Generator 函数是一个状态机,内部封装了不同状态的数据
用来生成遍历器对象
可暂停函数(惰性求值),yield 可暂停,next 方法可启动。每次返回的是 yield 后的表达式结果
特点:
function 与函数名之间有一个星号
内部用 yield 表达式来定义不同的状态
例如:
generator 函数返回的是指针对象,而不会执行函数内部逻辑
调用 next 方法函数,内部逻辑开始执行,遇到 yield 表达式停止,返回 {value: yield后的表达式结果/return后的返回结果(如果没写,返回undefined),done: boolean值(后面还有返回false,没有返回true)}
再次调用 next 方法会从上一次停止时的 yield 处开始,直到最后
yield 语句返回结果通常为 undefined,当调用 next 方法时传参内容会作为启动时 yield 语句的返回值
补充:
对象的 Symbol.iterator 属性,指向遍历器对象
例如:
发送 ajax 请求获取新闻内容
新闻内容获取成功后再次发送请求,获取对应的新闻评论内容
新闻内容获取失败则不需要再次发送请求
9、模块
导入
静态的
import语句用于导入由另一个模块导出的绑定在浏览器中,
import语句只能在声明了type="module"的script的标签中使用还有一个类似函数的动态
import(),它不需要依赖type="module"的 script 标签
语法:
导出
在创建 JavaScript 模块时,export 语句用于从模块中导出实时绑定的函数、对象或原始值,以便其他程序可以通过 import 语句使用它们
10、其他
尾调用优化
五、ES 2016
新增了两个新特性
1、指数操作
指数运算符(幂): **
2、数组新方法
Array.prototype.includes(value): 判断数组中是否包含指定 value
六、ES 2017
1、async/await 函数
概念:真正意义上去解决异步回调的问题,同步流程表达异步操作
本质:Generator 的语法
语法:
特点:
不需要像 Generator 去调用 next 方法,遇到 await 等待,当前的异步操作完成就往下执行
返回的总是 Promise 对象,可以用 then 方法进行下一步操作
async 取代 Generator 函数的
*,await 取代 Generator 的 yield语义上更为明确,使用简单,暂时没有任何副作用
获取新闻内容案例
改进一下,由于这种写法 error 并不会显示错误信息
给个模板
2、对象
Object.values:返回对象的所有值Object.entries:返回对象的所有键值对
3、字符串填充
padStart()、padEnd() 分别可以在字符串位数不足的时候向头部和尾部进行填充内容
第一个参数是总位数,第二个参数为位数不足时填充的内容
例如:
4、参数可以有多余的逗号
5、其他
getOwnPropertyDescriptors:获取对象的所有属性,包括不可枚举的属性共享内存和原子操作
后续好用的新特性
问号
可选链:?.
双问号:??
两个结合使用
由于现在开发都会用到 Babel 转译代码,所以可以放心使用这些新特性
最后更新于