> ## Content Index
> Fetch the complete content index at: https://iiong.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# ES2020 新特性
- URL: https://iiong.com/es2020-new-features-note/
- Published: 2022-03-14T04:07:35.000Z
- Updated: 2026-06-22T15:32:10.000Z
- Description: 对 ES2020 新特性掌握还是不够彻底，故写笔记记录下。
- Author: 淮城一只猫
- Tags: 编程技术, Web 前端

### null 运算符

`??`运算符是 `ES2020` 引入，也被称为`null`判断运算符( Nullish coalescing operator)

它的行为类似`||`，但是更严

`||` 运算符是左边是空字符串或 `false` 或 `0` 等 **falsy 值**，都会返回后侧的值。而 `??` 必须运算符左侧的值为 `null` 或 `undefined` 时，才会返回右侧的值。因此 `0 || 1` 的结果为1，`0 ?? 1` 的结果为 `0`。

```javascript
const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const undefinedValue = response.settings.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings.showSplashScreen ?? true; // result: false

```

---

### 链判断运算符

`?.` 也是 ES2020 引入，有人称为链判断运算符（optional chaining operator）

`?.` 直接在链式调用的时候判断，判断左侧的对象是否为 `null` 或 `undefined` ，如果是的，就不再往下运算，返回 `undefined`，如果不是，则返回右侧的值。

注： 常见写法

- `obj?.prop` 对象属性
- `obj?.[expr]` 对象属性
- `func?.(...args)` 函数或对象方法的调用

```javascript
var street = user.address && user.address.street;

var fooInput = myForm.querySelector('input[name=foo]')
var fooValue = fooInput ? fooInput.value : undefined

// 简化
var street = user.address?.street
var fooValue = myForm.querySelector('input[name=foo]')?.value

```

---

### 动态 import() 加载

我们可以使用 `import` 语句初始化的加载依赖项

```javascript
import defaultExport from "module-name";
import * as name from "module-name";
//...

```

但是静态引入的 `import` 语句需要依赖于 `type="module"` 的 `script` 标签，而且有的时候我们希望可以根据条件来按需加载模块，比如以下场景：

- 当静态导入的模块很明显的降低了代码的加载速度且被使用的可能性很低，或者并不需要马上使用它
- 当静态导入的模块很明显的占用了大量系统内存且被使用的可能性很低
- 当被导入的模块，在加载时并不存在，需要异步获取
- 当被导入的模块有副作用，这些副作用只有在触发了某些条件才被需要时

这个时候我们就可以使用动态引入 `import()`，它跟函数一样可以用于各种地方，返回的是一个 `promise`

基本使用如下两种形式：

```javascript
//形式 1
import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  })

 //形式2
let module = await import('/modules/my-module.js')

```

---

### 顶级 await

顶层 `await` 允许开发者在 `async` 函数外部使用 `await` 字段：

```javascript
//以前
(async function () {
  await Promise.resolve(console.log('🎉'))
  // → 🎉
})()

//简化后
await Promise.resolve(console.log('🎉'))

```

---

### String.prototype.replaceAll()

`String.prototype.replaceAll()` 用法与 `String.prototype.replace()` 类似

但是 `replace` 仅替换第一次出现的子字符串，而 `replaceAll` 会替换所有

例如需要替换所有 a 为 A ：

```javascript
// 以前
console.log('aaa'.replace(/a/g,'A')) //AAA

// 简化后
console.log('aaa'.replaceAll('a','A')) //AAA

```

---

### Array.prototype.at()

`Array.prototype.at()` 接收一个正整数或者负整数作为参数，表示获取指定位置的成员

参数正数就表示顺数第几个，负数表示倒数第几个，这可以很方便的某个数组末尾的元素：

```javascript
var arr = [1, 2, 3, 4, 5]
// 以前获取最后一位
console.log(arr[arr.length-1]) //5
// 简化后
console.log(arr.at(-1)) // 5

```

---

### 使用哈希前缀 `#` 将类字段设为私有

在类中通过哈希前缀 `#` 标记的字段都将被私有，子类实例将无法继承：

```javascript
class ClassWithPrivateField {
    #privateField;
    #privateMethod() {
        return 'hello world';
    }
    constructor() {
        this.#privateField = 42;
    }
}

const instance = new ClassWithPrivateField()
console.log(instance.privateField); //undefined
console.log(instance.privateMethod); //undefined

```

---

### globalThis

`globalThis` 可以理解为运行环境下 `this` 的全局对象：

```javascript
globalThis.setTimeout === window.setTimeout
// true

```