目录
ES2021(ES12)
let、const关键字和块级作用域
函数的扩展
数值的扩展
字符串的扩展
数组的扩展
对象的扩展
模块化
解构赋值
Symbol
Promise
Iterator
Generator
Proxy和Reffect
Set、Map、WeakSet、WeakMap
指数运算符
Array.prototype.includes()方法
async/await语法糖
Atomics对象
对象扩展
函数扩展
字符串扩展
异步迭代
正则的扩展
对象展开运算符
Promise.prototype.finally()
优化
trimStart()/trimLeft()和trimEnd()/trimRight()
Object.fromEntries()
Symbol.prototype.descrption
BigInt数据类型
globalThis对象
空值合并运算符
可选链操作符
Promise.allSettled()
String.prototype.replaceAll()
数值分隔符
WeakRef
Promise.any()
逻辑赋值操作符
ES2022
class的扩展
await在顶层使用
Object.hasOwn()
Array.prototype.at()
d修饰符
写在最后
首页 web前端 js教程 JavaScript ECMAScript 6所有新特性总结

JavaScript ECMAScript 6所有新特性总结

Aug 15, 2022 pm 05:01 PM
javascript

本篇文章给大家带来了关于javascript的相关知识,主要介绍了JavaScript ECMAScript 6(ES2015~ES2022)所有新特性总结,文章围绕主题展开详细的内容介绍,具有一定的参考价值,下面一起来看一下,希望对大家有帮助。

JavaScript ECMAScript 6所有新特性总结

【相关推荐:javascript视频教程web前端

自从ECMAScript在2015年正式发布了ES6起,到现在已经有了8个年头了,而自从2015年起,每年的6月都会发布一个新的版本,以当时的年作为版本号。

在这众多的版本中已经出现了很多新特性,为了方便记忆,我将所有的新特性全部整理在这一篇文章中。

ps:有的资料称ES2015后的所有版本统称为ES6,也有的称ES6表示ES2015,ES7表示ES2016以此类推,这里不做讨论。

ES2015(ES6)

ES2015是改动最大的一个版本,基本上对ES2015之前的所有的内容都做了扩展,大体如下图所示:

JavaScript ECMAScript 6所有新特性总结

let、const关键字和块级作用域

在ES6之前只有一种声明变量的方式,就是使用var关键字,在ES2015中新增了letconst关键字来声明变量与常量,

代码如下:

// 声明变量
let v = 100
v = 200
// 声明常量
const V = 200
// 修改常量
// V = 300 // 报错
登录后复制

同时使用letconst关键字声明的变量或者常量是具有块级作用域的,

示例代码如下:

{
  var v = 100
}
{
  let val = 200
}
console.log(v)
console.log(val) // 报错 val is not defined
登录后复制

值得注意的是使用let或者const关键字声明的变量不具有变量提升的特性,且存在暂时性死区的特性。

函数的扩展

在ES2015中允许函数使用默认值,示例代码如下:

// es2015之前
function foo(v) {
  v = v ? v : 100
  return v
}
// es2015
function bar(v = 100) {
  return v
}
登录后复制

值得注意的是如果有多个参数时,默认参数必须从后向前使用

在ES2015中新增了箭头函数,这是函数的一种简写形式示例代码如下:

function foo(v) {
  return v``
}
// 箭头函数写法
const foo = (v) => {
  return v
}
// 简写形式 1
const foo = v => { // 只有一个参数可以省略括号
  return v
}
// 简写形式 2
const foo = v => v // 语句中只有return时可以省略return和花括号
登录后复制

值得注意的是箭头函数的this是根据执行上下文决定的,内部并不会绑定this

使用箭头函数时内部并不存在arguments对象,而是采用剩余参数的方式代替,

示例代码如下:

const foo = (...args) => {
  // console.log(arguments) // ReferenceError: arguments is not defined
  console.log(args) // args 是一个数组
}
foo(1, 2, 3, 4) // [ 1, 2, 3, 4 ]
登录后复制

在ES2015中为函数增加的要给name属性,该属性指向函数的名称,

示例代码如下:

function foo(v) {
  return v
}
const bar = v => v
console.log(foo.name) // foo
console.log(bar.name) // bar
登录后复制

数值的扩展

在ES2015中对数值的扩展主要时为MathNumber两个对象增加一些方法,以及二进制和八进制的表示方法。

在ES2015中使用0b或者0B表示二进制,使用0o或者0O表示八进制。

示例代码如下:

console.log(0b111111111 === 511) // true
console.log(0o777 === 511) // true
登录后复制

为Number扩展的属性和方法如下:

属性/方法名描述
Number.EPSILON数值最小精度
Number.MIN_SAFE_INTEGER最小安全数(-2^53)
Number.MAX_SAFE_INTEGER最大安全数(2^53)
Number.parseInt()把参数解析为整数并返回
Number.parseFloat()把参数解析为浮点数并返回
Number.isFinite()判断是否为有限数值
Number.isNaN()判断是否为NaN
Number.isInteger()判断是否为整数
Number.isSafeInteger()判断数值是否在安全范围内

为Math扩展的方法如下:

方法名描述
Math.trunc()返回数值整数部分
Math.sign()返回数值类型(正数1、负数-1、零0)

字符串的扩展

ES2015引入模板字符串,使用反引号(`)定义,模板字符串会保留格式,且可以使用变量,

示例代码如下:

// 使用 ` 定义模板字符串
let str = `一碗周`
// 模板字符串可以保留格式
let str2 = `一
碗
周`
// 模板字符串可以使用变量
const myName = '一碗周'
let str3 = `author: ${myName}` // 使用 ${} 进行包裹
登录后复制

ES2015还为String和String的实例扩展了一些方法,如下:

方法名描述
String.fromCodePoint()用于从 Unicode 码点返回对应字符
String.raw()返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。
String.prototype.codePointAt()返回字符对应码点(String.fromCodePoint()的逆操作)
String.prototype.normalize()把字符的不同表示方法统一为同样形式,返回新字符串(Unicode正规化)
String.prototype.repeat()把字符串重复n次,返回处理后的字符串
String.prototype.includes()判断是否存在指定字符串
String.prototype.startsWith()判断字符串是否存在原始字符串的头部
String.prototype.endsWith()判断字符串是否存在原始字符串的尾部

数组的扩展

在ES2015中提供了展开运算符,即...,在数组中使用可以将数组展开,并以逗号分隔,

示例代码如下:

const arr = [1, 2, 3, 4, 5, 6]
const newArr = [...arr] // 复制数组
console.log(Math.max.call(null, ...arr)) // 将数组中的每一项作为参数使用
登录后复制

除此之外,还为Array以及数组提供了一系列方法,来逐个介绍:

Array.from()将类数组对象或者可迭代对象创建为一个新的数组,示例代码如下:

function foo() {
  return Array.from(arguments) // 将 arguments 转换为数组
}

console.log(foo(1, 2, 3, 4, 5, 6)) // [ 1, 2, 3, 4, 5, 6 ]
登录后复制

Array.of()创建一个具有可变数量参数的新数组实例,示例代码如下:

Array.of(1) // [1]
Array.of(true, 1, '一碗周') // [true, 1, '一碗周']
登录后复制

Array.prototype.copyWithin(),浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。

示例代码如下:

const arr = [1, 2, 3, 4]

// 从索引 2 开始,到结束 将内容复制到索引 0 的位置
arr.copyWithin(0, 2) // [ 3, 4, 3, 4 ]
登录后复制

Array.prototype.find()根据给定的回调函数,找到匹配的第一个元素,找不到返回undefined,示例代码如下:

const arr = [1, 2, 3, 4]
arr.find(item => item === 2) // 2(表示元素)、
登录后复制

Array.prototype.findIndex()根据给定的回调函数,找到匹配的第一个元素的索引,找不到返回-1,示例代码如下:

const arr = [1, 2, 3, 4]
arr.findIndex(item => item === 2) // 1 (表示索引)
登录后复制

Array.prototype.fill()将给定值填充数组示例代码如下:

const arr = [1, 2, 3, 4]
// 将给定值填充索引1-3
arr.fill('一碗周', 1, 3) // [ 1, '一碗周', '一碗周', 4 ]
登录后复制

Array.prototype.keys()返回一个可迭代的对象,其内容为数组的key示例代码如下:

const arr = [1, true, '一碗周']
const keys = arr.keys()
for (const i of keys) {
  console.log(i) // 遍历结果 0 1 2
}
登录后复制

Array.prototype.values()返回一个可迭代的对象,其内容为数组的value

示例代码如下:

const arr = [1, true, '一碗周']
const values = arr.values()
for (const i of values) {
  console.log(i) // 遍历结果 1 true 一碗周
}
登录后复制

Array.prototype.entries(),返回一个可迭代的对象,其内容是一个数组,索引0为原数组的元素,1为原数组该位置的值,

示例代码如下:

const arr = [1, true, '一碗周']

const iterator = arr.entries()
console.log(Array.from(iterator)) // [ [ 0, 1 ], [ 1, true ], [ 2, '一碗周' ] ]
登录后复制

对象的扩展

ES2015中允许对象的属性名和属性值一致时可以只写属性名,

示例代码如下:

const myName = '一碗周'
const age = 18
const person = { myName, age }
console.log(person) // { myName: '一碗周', age: 18 }
登录后复制

还有就是在定义对象时,允许使用[]包裹表达式作为属性名,示例代码如下:

const myName = '一碗周'
const age = 18
const person = {
  myName,
  ['a' + 'g' + 'e']: age,
}
console.log(person) // { myName: '一碗周', age: 18 }
登录后复制

Object.is():用于比较两个值是否相等,用于解决NaN ≠= NaN,+0 === -0的问题,

示例代码如下:

console.log(NaN === NaN) // false
console.log(+0 === -0) // true

console.log(Object.is(NaN, NaN)) // true
console.log(Object.is(+0, -0)) // false
登录后复制

Object.assign():将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象,

示例代码如下:

const person = Object.assign({}, { name: '一碗周' }, { age: 18 })
console.log(person) // { name: '一碗周', age: 18 }
登录后复制
  • Object.getPrototypeOf()获取原型对象
  • Object.setPrototypeOf()设置原型对象

在ES2015中提出了类的概念,在语法的层面上有了类,示例代码如下:

class Person {
  constructor(age) {
    // 属性
    this.myName = '一碗周'
    this.age = age
  }
  // 静态方法
  static print() {
    console.log()
  }
  // 访问器
  get myName() {
    console.log('getter')
    return '一碗周'
  }
  set myName(v) {
    console.log('setter' + v)
  }
  setName(v) {
    this.myName = v
  }
}
const person = new Person(18)
person.setName('ywanzhou') // 触发 setter 访问器
console.log(person.myName) // 触发 getter 访问器
登录后复制

模块化

在ES2015中提出ESModel模块化规范,这是第一个官方层面的模块化规范,在这个规范中允许我们使用export导出模块,使用import引入模块,

示例代码如下:

import a from 'm' // 导入模块 m 中的默认导出,将其命名为 a
import a, { b } from 'm' // 导入模块 m 中的默认导出以及单独导入成员 b
import * as A from 'm' // 导入模块中的所有成员
import 'm' // 执行 m 模块

export const b = 1 // 单独导出
export default b // 默认导出
export { b } // 按需导出
export { b as bb } // 改名导出
export { b } from 'm' // 导入模块 m 中的成员 b 并导出
登录后复制

解构赋值

ES2015新增了解构赋值的语法,允许我们使用按照一定的模式,在数组或者对象中提取指定的值,

示例代码如下:

// 数组的解构赋值
let [name, age, hobby = 'coding' /* 结构赋值的默认值 */] = ['一碗周', 18]
// 交换两个变量的值
let a = 1
let b = 2
;[a, b] = [b, a]
console.log(a, b) // 2 1

// 对象的结构赋值
let { name: ObjName /* 解构赋值重命名 */, sex } = { name: '一碗周', sex: 1 }

// 函数参数的解构赋值
function bar({ name, age }) {
  return name + age
}
bar({ name: '一碗周', age: 18 }) // 一碗周18
登录后复制

Symbol

Symbol是ES2015中新增的一种数据类型,通过Symbol()方法创建,可以传递一个字符串作为参数,用于描述该Symbol;

通过Symbol()方法创建的symbol值都是唯一的,示例代码如下:

/**
 * 语法
 * Symbol([description])
 * * description -> 是一个可选的描述信息
 */
// 创建一个 Symbol 类型的值
const mySymbol = Symbol()
console.log(mySymbol) // Symbol()

const myName = Symbol('一碗周')
console.log(typeof myName) // symbol
登录后复制

Symbol还有一系列属性和方法这里就不作介绍了。

Promise

Promise是ES2015中提供的一个异步解决方案,解决了回调地狱的问题。

通过Promise()构造函数可以创建一个promise对象,每一个Promise对象都具有以下几种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • resolved: 意味着操作成功完成。
  • rejected: 意味着操作失败。

状态的切换只有两种,分别是:

  • pending→resolved
  • pending→resolved

一旦状态发生改变,就不会再次改变

Promise实例中存在要给then方法,允许我们在Promise实例中链式调用,每个then方法还会返回一个Promise实例,

如下图所示:

JavaScript ECMAScript 6所有新特性总结

示例代码如下:

new Promise((resolve, reject) => {
    console.log('我是第一个Promise中的log')
    resolve()
})
    .then(() => {
        console.log('我是第一个then中的log')
    })
    .then(() => {
        console.log('我是第二个then中的log,但是我出现了异常')
        throw new Error('Error')
    })
    .then(() => {
        console.log('我是第三个then中的第一个回调的log,但是我不会执行,因为我上面出现了异常')
    }, () => {
        console.log('我是第三个then中的第二个回调的log,我执行了')
    })
    .then(() => {
        console.log('我是第四个then中的log,我可以正常执行')
    })

/* 执行结果如下
我是第一个Promise中的log
我是第一个then中的log
我是第二个then中的log,但是我出现了异常
我是第三个then中的第二个回调的log,我执行了
我是第四个then中的log,我可以正常执行
*/
登录后复制

有关Promise的一些方法如下:

  • Promise.prototype.then():它最多需要有两个参数:Promise的成功和失败情况的回调函数;
  • Promise.prototype.catch():等于then方法的第二个参数;
  • Promise.all():将多个实例包装成一个新实例,返回全部实例状态变更后的结果数组(齐变更再返回)
  • Promise.race():将多个实例包装成一个新实例,返回全部实例状态优先变更后的结果(先变更先返回)
  • Promise.resolve():将对象转为Promise对象(等价于new Promise(resolve => resolve()))
  • Promise.reject():将对象转为状态为rejected的Promise对象(等价于new Promise((resolve, reject) => reject()))

Iterator

Iterator即迭代器,它是一种接口,为各种不同的数据结构提供了统一的访问机制,换句话说,只要有任何数据结构部署了迭代接口,就可以使用统一的方式的来遍历它。

实现可迭代接口的数据结构,一般都自身实现或继承了以Symbol.iterator属性的,就属于可迭代对象。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。

一个包含next()方法的对象,才可以称为一个迭代对象。next()对象的会有返回一个对象,对象中包含两个值,

如下所示:

  • value:迭代器返回的任何JavaScript值。donetrue时可省略。
  • done:一个布尔值,为false时表示迭代未停止,为true时立即停止迭代器,且可以省略value的值。

JavaScript原生提供的迭代器接口如下图所示:

JavaScript ECMAScript 6所有新特性总结

现在我们为obj来实现一个迭代器,代码如下:

const obj = {
    [Symbol.iterator] () {
        return {
            next () {
                console.log('迭代器执行了');
                return {
                    value: '',
                    done: true // 标志是否结束,true表示已经结束
                }
            }
        }
    }
}
登录后复制

我们在next()方法中添加了一个打印,为了验证迭代器执行了,最终的运行结果为

迭代器执行了

Generator

Generator是ES2015中提供的一种异步编程解决方案,定义Generator函数在function关键字和函数名中间使用*星号,函数内部使用yield关键字定义不同的状态。

示例代码如下:

function* testGenerator() {
  // yield定义一个状态
  yield '一碗周'
  yield 'es新特性'
  return 'generator' // 终结Generator,后面即使有yield关键字也无效
}
const g = testGenerator() // 返回 Generator 对象,通过next()方法移动状态

g.next()
/* { value: '一碗周', done: false } */

g.next()
/* { value: 'es新特性', done: false } */

g.next()
/* { value: 'generator', done: true } */
登录后复制

Proxy和Reffect

Proxy对象用于创建一个代理对象,从而实现基本操作的拦截和自定义,基本操作包含13种,如下表所示:

拦截 ⽅法触发⽅式
get(target, propKey, receiver)读取某个属性
set(target, propKey, value, receiver)写⼊某个属性
has(target, propKey)in操作符
deleteProperty(target, propKey)delete操作符
getPrototypeOf(target)Object.getPropertypeOf()
setPrototypeOf(target, proto)Object.setPrototypeOf()
isExtensible(target)Object.isExtensible()
preventExtensions(target)Object.preventExtensions()
getOwnPropertyDescriptor(target, propKey)Object.getOwnPropertyDescriptor()
defineProperty(target, propKey, propDesc)Object.defineProperty()
ownKeys(target)Object.keys() 、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()
apply(target, thisArg, args)调⽤⼀个函数
construct(target, args)⽤ new 调⽤⼀个函数

Vue3就是基于Proxy进行编写的,下面这段代码展示了Proxy对象的使用:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.min.css" rel="external nofollow"  rel="stylesheet" />
  <title>通过set自动更新dom</title>
</head>

<body>
  <div style="width: 300px; margin: 100px auto">
    <div>
      <h1 id="name"></h1>
      <button id="btn" class="btn btn-primary">修改</button>
    </div>
  </div>
  <script>
    // 获取DOM节点
    const name = document.getElementById(&#39;name&#39;)
    const btn = document.getElementById(&#39;btn&#39;)
    // 定义一个修改值的函数
    const updateDOM = (el, value) => {
      el.innerHTML = value
    }
    const person = new Proxy({
      name: &#39;一碗粥&#39;,
    }, {
      set(target, propKey, value) {
        // 如果里面的值改变就去调用我们的updateDOM
        updateDOM(name, value)
        target[propKey] = value
        return true
      },
    })
    name.innerHTML = person.name
    // 点击按钮触发修改操作
    btn.addEventListener(&#39;click&#39;, () => {
      person.name === &#39;一碗周&#39; ?
        (person.name = &#39;一碗粥&#39;) :
        (person.name = &#39;一碗周&#39;)
    })
  </script>
</body>
</html>
登录后复制

上面的代码就利用set方法进行数据绑定,如果对象发生改变,就自动更新我们的DOM。

Reflect是ECMAScript2015提供的一个对象,它提供了一些拦截JavaScript操作的静态方法,这些方法与Proxy中的handlers中的方法一致。

Reflect并不是一个构造函数,也就是说它不能够被实例化。

Proxy对象中的每一个拦截操作(例如:getdelete等),内部都对应的调用了Reflect的方法。它提供的静态方法与Proxy中的handlers中的方法名称都一致,

具体如下:

默认调⽤功能
Reflect.get()获取对象身上某个属性的值
Reflect.set()在对象上设置属性
Reflect.has()判断一个对象是否存在某个属性
Reflect.deleteProperty()删除对象上的属性
Reflect.getPrototypeOf()获取指定对象原型的函数
Reflect.setPrototypeOf()设置或改变对象原型的函数
Reflect.isExtensible()判断一个对象是否可扩展 (即是否能够添加新的属性)
Reflect.preventExtensions()阻止新属性添加到对象
Reflect.getOwnPropertyDescriptor()获取给定属性的属性描述符
Reflect.defineProperty()定义或修改一个对象的属性
Reflect.ownKeys()返回由目标对象自身的属性键组成的数组
Reflect.apply()对一个函数进行调用操作,同时可以传入一个数组作为调用参数
Reflect.construct()对构造函数进行 new操作,实现创建类的实例

Set、Map、WeakSet、WeakMap

SetMapWeakSetWeakMap是ES2015中新增的几个对象:

  • SetWeakSet与数组类似,准确的它他们是集合,这两者的区别就是Set可以存储任何数据类型,而WeakSet只能存储对象的引用,而且是弱引用;

Set对象在实际开发中最常见的就是实现数据去重,示例代码如下:

const arr = [1, 2, 2, 3, 4, 3, 5]
const set = new Set(arr)
// set对象可以使用 ... 展开 所有项
console.log([...set]) // [ 1, 2, 3, 4, 5 ]
登录后复制
  • MapWeakMap与对象类似,存储方式是键值对形式的,这两者的区别Map的键值对都是可以是任意的而WeakMap键必须是对象的引用而值可以是任意类型的。

ES2016(ES7)

ES2016发布的新特性比较少,主要就两个新特性,如下图所示:

JavaScript ECMAScript 6所有新特性总结

指数运算符

ES2016中新增指数**,也叫幂运算符,与Math.pow()有着一样的功能,

示例代码如下:

console.log(2 ** 10 === Math.pow(2, 10)) // true
登录后复制

Array.prototype.includes()方法

在ES2016中在数组原型上增加了includes()方法,该方法用于判断一个数组中是否包含指定的值,返回一个布尔值,

示例代码如下:

const arr = [1, 2, 3, 4, 5, NaN]
console.log(arr.indexOf(NaN)) // -1
console.log(arr.includes(NaN)) // true
登录后复制

值得注意的是使用includes()NaNNaN+0-0是相等的。

ES2017(ES8)

JavaScript ECMAScript 6所有新特性总结

async/await语法糖

Promise的出现虽然解决了回调地狱的问题,但是如果链式调用特别多的话可读性还是会变差,在ES2017中新增了 async/await语法糖解决了这个问题。

Promise的写法如下:

;(function () {
  function promise(v) {
    return new Promise((resolve, reject) => {
      resolve(v)
    })
  }
  const p = promise(1)
  p.then(res => {
    return promise(res)
  }).then(res => {
    console.log(res)
  })
})()
登录后复制

如果下一个Promise依赖于上一个,这种链式调用就会非常的长,现在我们用 async/await语法糖改写一下:

;(async function () {
  function promise(v) {
    return new Promise((resolve, reject) => {
      resolve(v)
    })
  }
  const r1 = await promise(1)
  const r2 = await promise(r1)
  const res = await promise(r2)
  console.log(res)
})()
登录后复制

可以看到,我们可以利用 async/await语法糖将Promise改写为平级的写法。

Atomics对象

ES2017中新增了Atomics对象,该对象提供了一系列静态方法用于操作SharedArrayBuffer和ArrayBuffer对象,该对象并不能使用new关键字进行实例化,仅仅提供了一些静态的属性和方法

对象扩展

在ES2017中为Object扩展了三个静态方法,如下所示:

  • Object.values():返回一个给定对象自身的所有可枚举属性值的数组;
  • Object.entries():返回一个给定对象自身可枚举属性的键值对数组;
  • Object.getOwnPropertyDescriptors():返回给定对象所有自有属性的属性描述符。

函数扩展

在ES2017中允许我们在函数参数列表的最后面添加逗号,这个小特性非常的有用,因为为尾逗号的更新的时候仅仅需要改动一行代码,如果不适用尾逗号则是改动两行代码。

实例代码如下:

function fun(
  aaaaa,
  bbbbb,
  ccccc,
) {}
登录后复制

如果存在尾逗号,只需要在最后面添加一行就好;如果不存在则需要在后面添加要给逗号,然后在添加一行。这在版本管理中就改动了两行,而不是一行。

字符串扩展

在ES2017中为字符串新增了两个实例方法,分别是:

  • padStart():在字符串开头填充空格;
  • padEnd():在字符串结尾填充空格;

示例代码如下:

const str = &#39;一碗周&#39;
console.log(str.padStart(10)) /*        一碗周 */
console.log(str.padEnd(10))   /* 一碗周        */
登录后复制

ES2018(ES9)

JavaScript ECMAScript 6所有新特性总结

异步迭代

在ES2018中新增了for await...of语句,该用于可以遍历异步可迭代对象,

示例代码如下:

var asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return Promise.resolve({ value: this.i++, done: false })
        }

        return Promise.resolve({ done: true })
      },
    }
  },
}
;(async function () {
  for await (num of asyncIterable) {
    console.log(num)
  }
})()

// 0
// 1
// 2
登录后复制

正则的扩展

在ES2018中,对正则表达式进行了如下扩展:

正则表达式分组命名:

在ES2018之前,我们无法对正则表达式中的分组命名,在ES2018中引入了该特性,该特性既方便了正则的阅读又方便了引用,

示例代码如下:

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/

const matchObj = RE_DATE.exec(&#39;2022-02-22&#39;)
const year = matchObj.groups.year // 2022
const month = matchObj.groups.month // 02
const day = matchObj.groups.day // 22
登录后复制

s修饰符/dotALl模式:新增的s修饰符允许使用.匹配任意单个字符,****属性表明是否在正则表达式中一起使用"s"修饰符。

反向断言:ES2018之前仅存在正向断言,而ES2018中新增了反向断言反向否定断言

对象展开运算符

ES2015中新增数组的展开运算符,在ES2018中将这一特性加入到了对象中,示例代码如下:

const n = { name: &#39;一碗周&#39; }
const a = { age: 18 }
const person = { ...n, ...a }
// 合并对象
console.log(person) // { name: &#39;一碗周&#39;, age: 18 }
登录后复制

Promise.prototype.finally()

finally()方法会返回一个Promise对象,当promise的状态变更,不管是变成rejected或者fulfilled,最终都会执行finally()的回调。

示例代码如下:

fetch(url)
  .then(res => {
    console.log(res)
  })
  .catch(error => {
    console.log(error)
  })
  .finally(() => {
    console.log(&#39;结束&#39;)
  })
登录后复制

ES2019(ES10)

JavaScript ECMAScript 6所有新特性总结

优化

在ES2019中优化了以下两个内容:

  • Function.prototype.toString():返回的函数体包含注释与空格;
  • try...catch:语句中的catch允许不使用参数,示例代码如下:
try {
  console.log(&#39;一碗周&#39;)
} catch {
  console.error(&#39;一碗周&#39;)
}
登录后复制

trimStart()/trimLeft()和trimEnd()/trimRight()

  • String.prototype.trimStart:用于去除字符串左边的空格;
  • String.prototype.trimLeft:它是trimStart的别名
  • String.prototype.trimEnd:用于去除字符串右边的空格;
  • String.prototype.trimRight:它是trimEnd的别名

数组的扩展

在ES2019中扩展了两个数组方法,分别是:

  • Array.prototype.flat():该方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回;简单的说就是实现数组的扁平化。
const arr = [0, 1, 2, [3, 4]]
console.log(arr.flat()) // [ 0, 1, 2, 3, 4 ]
登录后复制
  • Array.prototype.flatMap():该方法映射且扁平化数组,返回新数组(只能展开一层数组)。

Object.fromEntries()

ES2019中新增的Object.fromEntries()方法把键值对列表转换为一个对象,是Object.entries()方法的反操作,

示例代码如下:

const person = {
  name: &#39;一碗周&#39;,
  age: &#39;18&#39;,
}
const e = Object.entries(person)

const p = Object.fromEntries(e)
console.log(p) // { name: &#39;一碗周&#39;, age: &#39;18&#39; }
登录后复制

Symbol.prototype.descrption

description是一个只读属性,它会返回创建Symbol对象时的那个可选的描述字符串。

ES2020(ES11)

JavaScript ECMAScript 6所有新特性总结

模块化

在ES2020中加入了动态导入,也就是我们需要该模块的时候才会进行加载,这可以减少开销和页面加载时间,示例代码如下:

import(&#39;/modules/my-module.js&#39;).then(module => {
  // Do something with the module.
})
登录后复制

动态导入使用import()方法,它返回一个Promise。

在ES2020中,还为import增加一个meta对象,该对象给JavaScript模块暴露了特定上下文的元数据属性的对象。

BigInt数据类型

BigInt的出现时解决JavaScript中允许的最大数字是2**53-1的问题,BigInt 可以表示任意大的整数。

const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n
const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
// ↪ 9007199254740991n
登录后复制

globalThis对象

ES2020中引入globalThis,它是对全局对象的引入,在Node是的全局对象是Global,而浏览器环境是Window;如下代码展示的在有没有GlobalThis的区别:

// 之前
var getGlobal = function () { 
  if (typeof self !== &#39;undefined&#39;) { return self; } 
  if (typeof window !== &#39;undefined&#39;) { return window; } 
  if (typeof global !== &#39;undefined&#39;) { return global; } 
  throw new Error(&#39;unable to locate global object&#39;); 
}; 

var globals = getGlobal(); 

if (typeof globals.setTimeout !== &#39;function&#39;) { 
  // no setTimeout in this environment! 
}
登录后复制
// 之后

if (typeof globalThis.setTimeout !== &#39;function&#39;) {
  // no setTimeout in this environment!
}
登录后复制

空值合并运算符

空值合并运算符是由两个问号来表示,该运算符也是一个逻辑运算符,该运算符与逻辑或运算符类似。其计算规则为,只要左运算元为null或者undefined,则返回右运算元,否则返回左运算元。而逻辑或运算符只有左运算元转换为boolean类型后为false,就返回右运算元。

示例代码如下:

console.log(null ?? 10) // 10
console.log(undefined ?? 10) // 10
console.log(false ?? 10) // false
登录后复制

该运算符用于为没有值的变量赋值很有用,例如:如果这个数没有值,就为其赋值,否则不赋值,

示例代码如下:

var value

// 如果value的值不为 null 或者 undefined 为其赋值10
value = value ?? 10
console.log(value) // 10
登录后复制

值得注意的是空值合并运算符与逻辑与和逻辑或不能同时使用,否则会抛出异常,解决方案是通过使用()来表明优先级

可选链操作符

可选链操作符用于读取某对象链下深处属性的值,使用这个操作符不必验证对象下的每个属性必须存在,例如我们想要访问A.a.b这个属性时,我们首先需要确保A存在,然后需要确保A.a存在,才可以访问A.a.b这个属性,不然就会报错。

使用可选链操作符就不会出现这样的问题,当我们访问某个属性时,只要有一处不存在,就会返回undefind,不会报错。

var A = {}

// console.log(A.a.b) // 报错
console.log(A.a?.b) // undefined
登录后复制

可选链操作符也可用于对象下方法的调用,示例代码如下:

var obj = {}

// 如果存在 obj.fun() 这个方法,下面则会直接调用,如果不存在则会返回undefined
obj.fun?.A()
登录后复制

Promise.allSettled()

Promise.allSettled()方法返回一个在所有给定的 promise 都已经resolved或rejected后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。

ES2021(ES12)

JavaScript ECMAScript 6所有新特性总结

String.prototype.replaceAll()

replaceAll()方法返回一个新字符串,新字符串的内容是经过替换的,实例代码如下:

const str = &#39;一碗粥&#39;
const newStr = str.replaceAll(&#39;粥&#39;, &#39;周&#39;)
console.log(newStr) // 一碗周
登录后复制

数值分隔符

严格意义上讲数值分隔符(_)并不属于一个运算符,其作用就是使数字更加利于阅读,例如下面的代码

console.log(1_0000_0000) // 100000000
登录后复制

这个符号仅仅起到了便于阅读的目的,有与没有的结果并不影响,看下面的代码

1_1 === 11 // true
登录后复制

WeakRef

ES2021中新增的WeakRef对象允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被GC回收。

Promise.any()

ES2021中新增的Promise.any()方法,它接受的参数和与promise.all()是一致的,唯一不同的是,Promise.any()方法接受的可迭代对象中没有一个promise成功(即所有的promises都失败/拒绝),就返回一个失败的promise和AggregateError类型的实例。

逻辑赋值操作符

ES2021中新增了一些赋值运算符,具体如下:

  • &&=
  • ||=
  • ??=

实际上它与普通的赋值运算符一致,示例代码如下:

const [f1, f2, f3] = [true, false]
f1 &&= &#39;一碗周&#39; // 等同于 str = str && &#39;一碗周&#39;
f2 ||= &#39;一碗周&#39; // 等同于 str = str || &#39;一碗周&#39;
f3 ??= &#39;一碗周&#39; // 等同于 str = str ?? &#39;一碗周&#39;
登录后复制

ES2022

JavaScript ECMAScript 6所有新特性总结

class的扩展

在ES2022中允许我们并不在constructor中定义类的成员,示例代码如下:

class C {
  myName = &#39;一碗周&#39;
}
/* 两者是一致的 */
class C {
  constructor() {
    myName = &#39;一碗周&#39;
  }
}
登录后复制

如果成员只声明不初始化它的默认值是undefined。

在ES2022中允许我们使用#开头命名的变量作为类的私有成员,

示例代码如下:

class C {
  #myName = &#39;一碗周&#39;
}
const c = new C()
console.log(#myName) //  Private field &#39;#myName&#39; must be declared in an enclosing class
登录后复制

await在顶层使用

在ES2022中新增了允许在顶层使用await,在顶层可以不适用async函数进行包裹,示例代码如下:

import { AsyncFun } from &#39;module&#39;
await AsyncFun()
console.log(123)
登录后复制

Object.hasOwn()

Object.hasOwn()方法用于判断某个对象上是否具有某个属性,示例代码如下:

const person = {
  name: &#39;一碗周&#39;,
  age: 18,
}
console.log(Object.hasOwn(person, &#39;name&#39;)) // true
console.log(Object.hasOwn(person, &#39;sex&#39;)) // false
登录后复制

Array.prototype.at()

ES2022中新增的at()方法,它的作用是获取数组中的某个成员,它的参数是数组的索引,与直接使用索引的方式不同,它允许我们传递负值,等同于从后面倒数,示例代码如下:

const arr = [1, 2, 3, 4, 5, 6]
console.log(arr.at(-1)) // 6
// 等同于 arr[arr.length - 1]
登录后复制

d修饰符

正则表达式增加了一个/d修饰符,当使用正则表达式的exec()方法时,如果有/d修饰符,那么结果会多返回一个indices属性,用来表示匹配的结果的在原字符串中的起始index值。

示例代码如下:

const str = &#39;JavaScript&#39;
const r = /a/d

const m = r.exec(str)
console.log(m.indices[0]) //[ 1, 2 ]
登录后复制

写在最后

这篇文章到这就结束了,这篇文章中整理了ES2015到ES2022的新特性,有可能会有疏漏,望谅解。

脑图如下:

【相关推荐:javascript视频教程web前端

以上是JavaScript ECMAScript 6所有新特性总结的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统 如何使用WebSocket和JavaScript实现在线预约系统 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

javascript中如何使用insertBefore javascript中如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

如何在JavaScript中获取HTTP状态码的简单方法 如何在JavaScript中获取HTTP状态码的简单方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务

See all articles