ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript ECMAScript 6 のすべての新機能の概要

JavaScript ECMAScript 6 のすべての新機能の概要

WBOY
リリース: 2022-08-15 18:13:22
転載
1600 人が閲覧しました

この記事では、javascript に関する関連知識を紹介します。主に JavaScript ECMAScript 6 (ES2015~ES2022) のすべての新機能の概要を紹介します。この記事では、次のテーマを中心に詳細な内容を紹介します。以下に参考値を見てみましょう。皆様の参考になれば幸いです。

JavaScript ECMAScript 6 のすべての新機能の概要

[関連する推奨事項: JavaScript ビデオ チュートリアル Web フロントエンド ]

ECMAScript が正式にリリースされてからES6 がリリースされてから 8 年が経過し、2015 年からは毎年 6 月に今年をバージョン番号として新しいバージョンがリリースされます。

これらの多くのバージョンには多くの新機能が登場していますが、記憶を容易にするために、この記事ではすべての新機能を整理しました。

ps: ES2015 以降のすべてのバージョンを総称して ES6 と呼ぶという情報もありますし、ES6 は ES2015、ES7 は ES2016 などを意味するという情報もありますが、ここでは説明しません。

ES2015(ES6)

ES2015 は最も大きな変更が加えられたバージョンです。基本的に ES2015 より前のすべての内容が拡張されています。次の図に示すように:

JavaScript ECMAScript 6 のすべての新機能の概要

let、const キーワード、ブロック レベルのスコープ

ES6 より前には、変数を宣言する方法は 1 つだけでした。 ES2015 では、変数と定数を宣言するために let キーワードと const キーワードが追加されています。 #コードは次のとおりです。

// 声明变量
let v = 100
v = 200
// 声明常量
const V = 200
// 修改常量
// V = 300 // 报错
ログイン後にコピー
let

キーワードと

const キーワードの両方を使用して宣言された変数または定数は、ブロック レベルのスコープ # # を持ちます。 #サンプル コードは次のとおりです。

{
  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
}
ログイン後にコピー

注目に値します。 thatIf there 複数のパラメータがある場合、デフォルトのパラメータは後ろから前まで である必要があります。

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

は内部的にバインドされていないことに注意してください。 アロー関数を使用する場合、内部引数オブジェクトはありませんが、代わりに残りのパラメータが使用されます。

サンプル コードは次のとおりです:

const foo = (...args) => {
  // console.log(arguments) // ReferenceError: arguments is not defined
  console.log(args) // args 是一个数组
}
foo(1, 2, 3, 4) // [ 1, 2, 3, 4 ]
ログイン後にコピー

In ES2015 で関数に追加された name 属性は、関数の名前を指します。

サンプル コードは次のとおりです。

function foo(v) {
  return v
}
const bar = v => v
console.log(foo.name) // foo
console.log(bar.name) // bar
ログイン後にコピー

Extension of the function value ES2015 での数値の拡張では、主に

Math

Number

という 2 つのオブジェクトにいくつかのメソッドが追加され、さらにバイナリおよび 8 進数の表現メソッドが追加されます。 ES2015 では、バイナリを表すには 0b または

0B

を使用し、8 進数を表すには 0o または 0O を使用します。 サンプル コードは次のとおりです。

console.log(0b111111111 === 511) // true
console.log(0o777 === 511) // true
ログイン後にコピー

Number 用に拡張されたプロパティとメソッドは次のとおりです。

プロパティ/メソッド名説明数値の最小精度# Number.MIN_SAFE_INTEGER最小安全番号(-2^53)最大安全な数値(2^53)パラメータを整数に解析して返しますNumber.parseFloat()パラメータを浮動小数点数として解析して返しますNumber.isFinite()有限値かどうか判定Number.isNaN()NaNNumber かどうか判定.isInteger()NaN かどうかの判定整数の場合Number.isSafeInteger()値が安全な範囲内かどうかを判定 Math 用に拡張されたメソッドは次のとおりです。
Number.EPSILON
Number.MAX_SAFE_INTEGER
Number.parseInt()

メソッド名

DescriptionMath.trunc( )数値の整数部分を返しますMath.sign ()数値型を返します (正の数 1、負の数 -1、ゼロ 0)
<h3>字符串的扩展</h3><p>ES2015引入模板字符串,使用反引号(`)定义,模板字符串会保留格式,且可以使用变量,</p><p><strong>示例代码如下:</strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;">// 使用 ` 定义模板字符串 let str = `一碗周` // 模板字符串可以保留格式 let str2 = `一 碗 周` // 模板字符串可以使用变量 const myName = &amp;#39;一碗周&amp;#39; let str3 = `author: ${myName}` // 使用 ${} 进行包裹</pre><div class="contentsignin">ログイン後にコピー</div></div><p><strong>ES2015还为String和String的实例扩展了一些方法,如下:</strong></p><table><tbody><tr class="firstRow"><th>方法名</th><th>描述</th></tr><tr><td>String.fromCodePoint()</td><td>用于从 Unicode 码点返回对应字符</td></tr><tr><td>String.raw()</td><td>返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。</td></tr><tr><td>String.prototype.codePointAt()</td><td>返回字符对应码点(String.fromCodePoint()的逆操作)</td></tr><tr><td>String.prototype.normalize()</td><td>把字符的不同表示方法统一为同样形式,返回新字符串(Unicode正规化)</td></tr><tr><td>String.prototype.repeat()</td><td>把字符串重复n次,返回处理后的字符串</td></tr><tr><td>String.prototype.includes()</td><td>判断是否存在指定字符串</td></tr><tr><td>String.prototype.startsWith()</td><td>判断字符串是否存在原始字符串的头部</td></tr><tr><td>String.prototype.endsWith()</td><td>判断字符串是否存在原始字符串的尾部</td></tr></tbody></table><h3>数组的扩展</h3><p>在ES2015中提供了展开运算符,即...,在数组中使用可以将数组展开,并以逗号分隔,</p><p><strong>示例代码如下:</strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;">const arr = [1, 2, 3, 4, 5, 6] const newArr = [...arr] // 复制数组 console.log(Math.max.call(null, ...arr)) // 将数组中的每一项作为参数使用</pre><div class="contentsignin">ログイン後にコピー</div></div><p><strong>除此之外,还为Array以及数组提供了一系列方法,来逐个介绍:</strong></p><p><code>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, &#39;一碗周&#39;) // [true, 1, &#39;一碗周&#39;]
ログイン後にコピー

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(&#39;一碗周&#39;, 1, 3) // [ 1, &#39;一碗周&#39;, &#39;一碗周&#39;, 4 ]
ログイン後にコピー

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

const arr = [1, true, &#39;一碗周&#39;]
const keys = arr.keys()
for (const i of keys) {
  console.log(i) // 遍历结果 0 1 2
}
ログイン後にコピー

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

示例代码如下:

const arr = [1, true, &#39;一碗周&#39;]
const values = arr.values()
for (const i of values) {
  console.log(i) // 遍历结果 1 true 一碗周
}
ログイン後にコピー

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

示例代码如下:

const arr = [1, true, &#39;一碗周&#39;]

const iterator = arr.entries()
console.log(Array.from(iterator)) // [ [ 0, 1 ], [ 1, true ], [ 2, &#39;一碗周&#39; ] ]
ログイン後にコピー

对象的扩展

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

示例代码如下:

const myName = &#39;一碗周&#39;
const age = 18
const person = { myName, age }
console.log(person) // { myName: &#39;一碗周&#39;, age: 18 }
ログイン後にコピー

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

const myName = &#39;一碗周&#39;
const age = 18
const person = {
  myName,
  [&#39;a&#39; + &#39;g&#39; + &#39;e&#39;]: age,
}
console.log(person) // { myName: &#39;一碗周&#39;, 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: &#39;一碗周&#39; }, { age: 18 })
console.log(person) // { name: &#39;一碗周&#39;, age: 18 }
ログイン後にコピー
  • Object.getPrototypeOf()获取原型对象
  • Object.setPrototypeOf()设置原型对象

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

class Person {
  constructor(age) {
    // 属性
    this.myName = &#39;一碗周&#39;
    this.age = age
  }
  // 静态方法
  static print() {
    console.log()
  }
  // 访问器
  get myName() {
    console.log(&#39;getter&#39;)
    return &#39;一碗周&#39;
  }
  set myName(v) {
    console.log(&#39;setter&#39; + v)
  }
  setName(v) {
    this.myName = v
  }
}
const person = new Person(18)
person.setName(&#39;ywanzhou&#39;) // 触发 setter 访问器
console.log(person.myName) // 触发 getter 访问器
ログイン後にコピー

模块化

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

示例代码如下:

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

export const b = 1 // 单独导出
export default b // 默认导出
export { b } // 按需导出
export { b as bb } // 改名导出
export { b } from &#39;m&#39; // 导入模块 m 中的成员 b 并导出
ログイン後にコピー

解构赋值

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

示例代码如下:

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

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

// 函数参数的解构赋值
function bar({ name, age }) {
  return name + age
}
bar({ name: &#39;一碗周&#39;, age: 18 }) // 一碗周18
ログイン後にコピー

Symbol

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

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

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

const myName = Symbol(&#39;一碗周&#39;)
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(&#39;我是第一个Promise中的log&#39;)
    resolve()
})
    .then(() => {
        console.log(&#39;我是第一个then中的log&#39;)
    })
    .then(() => {
        console.log(&#39;我是第二个then中的log,但是我出现了异常&#39;)
        throw new Error(&#39;Error&#39;)
    })
    .then(() => {
        console.log(&#39;我是第三个then中的第一个回调的log,但是我不会执行,因为我上面出现了异常&#39;)
    }, () => {
        console.log(&#39;我是第三个then中的第二个回调的log,我执行了&#39;)
    })
    .then(() => {
        console.log(&#39;我是第四个then中的log,我可以正常执行&#39;)
    })

/* 执行结果如下
我是第一个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(&#39;迭代器执行了&#39;);
                return {
                    value: &#39;&#39;,
                    done: true // 标志是否结束,true表示已经结束
                }
            }
        }
    }
}
ログイン後にコピー

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

迭代器执行了

Generator

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

示例代码如下:

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

g.next()
/* { value: &#39;一碗周&#39;, done: false } */

g.next()
/* { value: &#39;es新特性&#39;, done: false } */

g.next()
/* { value: &#39;generator&#39;, 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 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:jb51.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート