SharedArrayBuffer
是一个固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer
。
可用于在共享内存上创建数据。与 ArrayBuffer
不同,SharedArrayBuffer
不能分离。
8. Atomics object
Atomics 对象,它提供了一组静态方法来对 SharedArrayBuffer
执行原子操作。原子的所有属性和函数都是静态的。
如果一个多线程同时在同一个位置读写数据,原子操作保证了正在操作的数据如预期的那样:即在上一个子操作结束后执行下一个,操作不中断。可以说是针对Node.Js
中多线程Server的开发而加强的功能,在前端开发中使用的机会相当低。chrome 已经提供了支持。
五、ES9 (ES2018)
- 循环等待
在异步函数中,有时需要在同步 for 循环中使用异步(非同步)函数。
async function process(array) {
for (const i of array) {
await doSomething(i);
}
}
async function process(array) {
array.forEach(async i => {
await doSomething(i);
});
}
上面的代码不会像预期的那样输出期望的结果。
for
循环本身还是同步的,会在循环中的异步函数完成之前执行整个for
循环,然后将里面的异步函数逐一执行。
ES9 增加了异步迭代器,允许 await
与 for
循环一起使用,逐步执行异步操作。
async function process(array) {
for await (const i of array) {
doSomething(i);
}
}
promise.finally()
无论是成功(.then()
)还是失败(.catch()
),Promise
后面都会执行的部分。Rest, Spread
在 ES2015 中,Rest
不定长度参数…,可以转换成数组传入。- 正则表达式组
RegExp 可以返回匹配的数据包
const regExpDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/;
const match = regExpDate.exec('2020-06-25');
const year = match[1]; // 2020
const month = match[2]; // 06
const day = match[3]; // 25
- 正则表达式 dotAll
.
表示匹配除输入以外的任何符号,添加这些标志后,允许匹配输入。
/hello.world/.test('hello\nworld'); // false
/hello.world/s.test('hello\nworld'); // true
六、ES10 (ES2019)
- 更友好的
JSON.stringify
如果输入是Unicode
但超出范围,则JSON.stringify
最初会返回格式错误的Unicode
字符串。
现在是第 3 阶段的提案,使其成为有效的 Unicode
并以 UTF-8
呈现。
Array.prototype.flat() & Array.prototype.flatMap()
展平阵列String.prototype.trimStart()
&String.prototype.trimEnd()
trimStart()
方法从字符串的开头删除空格,trimLeft()
是此方法的别名。Object.fromEntries()
Object.fromEntries()
方法将键值对列表转换为对象。String.prototype.matchAll
matchAll()
方法返回将字符串与正则表达式匹配的所有结果的迭代器,包括捕获组。fixed catch
绑定
在使用catch
之前,不管有用与否,一定要传入一个eparameter
来表示接收到的错误。
如果现在不用,可以省略。BigInt
(新数字类型)(重要)
BigInt
值,有时也称为 BigInt,是一个 bigint 原语,通过将 n 附加到整数文字的末尾,或通过调用BigInt()
函数(没有new
运算符)并给它一个整数值或字符串来创建值。
- ES5:
String, Number, Boolean, Null, Undefined
- ES6 新增:
Symbol
,到ES6就一共有6 种类型 - ES10 新增:
BigInt
,就达到 7 种类型
七、ES11 (ES2020)
Promise.allSettled()
Promise.allSettled()
方法返回一个在所有给定的Promise
都已实现或拒绝后实现的Promise
,并带有一组对象,每个对象都描述了每个Promise
的结果。
它通常用于当有多个不依赖于彼此成功完成的异步任务,或者总是想知道每个 Promise 的结果时。
相比之下,Promise.all()
返回的 Promise
可能更合适,如果任务相互依赖/如果想立即拒绝其中任何一个拒绝。
- 可选链操作符
?.
在开发中,很容易遇到先判断数据是否存在,判断是否写入。
const isUserExist = user && user.info;
if (isUserExist) {
username = user.info.name;
}
如果返回的数据为null
或者用户对象下没有相应属性,则会抛出Uncaught TypeError: Cannot read property...
。
导致程序无法继续执行
使用 ?.
,语法更简单
const username = user?.info?.name;
如果存在,获取name的值,如果不存在,赋值undefined
与 ||
一起使用,只需一行!
const username = user?.name || 'guest';
Nullish
合并运算符 ??
在JavaScript
中,遇到0、null
、undefined
时会自动转为false
。
但有时0其实是一个正常的值,只能容错undefined
和null
,但是使用??
,可以保持简洁。- Dynamic-import
从字面上看,应该很容易理解,就是在需要的时候加载相关的逻辑。 - GlobalThis
全局globalThis
属性包含全局this
值,类似于全局对象。
八、ES12 (ES2021)
Promise.any()
Promise.any()
接受一个可迭代的Promise
对象。它返回一个单一的Promise
,只要iterable
中的任何一个Promise
完成,就会返回一个Promise
,并带有已完成的Promise
的值。
如果可迭代的实现中没有任何承诺(如果所有给定的承诺都被拒绝),则返回的承诺会被 AggregateError
拒绝,AggregateError
是 Error
的一个新子类,它将单个错误组合在一起。
- 逻辑赋值运算符
在开发过程中,可以使用 ES2020 中提出的逻辑运算符||
、&&
和 `??(Nullish coalescing operator)来解决一些问题。
而 ES2021 会提出 ||=
, &&=
, ??=
,概念类似于 +=
:
let b = 2
b += 1
// equal to b = b + 1
let a = null
a ||= 'some random text' // a become to'some random text'
// equal a = a || 'some random text'
let c = 'some random texts'
c &&= null // c become to null
// equal to c = c && null
let d = null
d ??= false // d become to false
// equal to d = d ?? false
WeakRef
WeakRef
对象包含对对象的弱引用,该对象称为其目标或引用对象。对对象的弱引用是不会阻止对象被垃圾收集器回收的引用。相反,普通(或强)引用将对象保存在内存中,当一个对象不再有任何强引用时,JavaScript
引擎的垃圾收集器可能会销毁该对象并回收其内存。如果发生这种情况,将无法再从弱引用中获取对象。
九、ES13 (ES2022)
ES13 带来了 6 个新特性:
- 模块顶层作用域支持
await
表达式。 - 新增私有类元素(
#
)、静态块;in 操作符支持私有类元素。 - 正则新增
d
标志和其对应的hasIndices
属性,提供了获取捕获组开始索引和结束索引的方法。 Error
实例增加cause
属性,可携带更多错误信息。Strings
、Arrays
、TypedArrays
新增at
方法,支持关联访问。Object.hasOwn
代替Object.prototype.hasOwnProperty
,判断对象是否含有属性。
9.1 Strings、Arrays、TypedArrays 的 at 方法
利用下标访问数组元素时,下标会被转换为字符串,负数下标也对应着一个独立的数组元素,所以 Js 的数组是不支持关联访问的。ES13 新增了 at
方法,可以利用负数索引进行关联访问,例如以下示例,可以利用 at
方法和负数索引 -2 来访问倒数第二个元素。
const array = [5, 12, 8, 130, 44];
array.at(-2); // 130
9.2 私有类元素
在类的定义中,以 “#
” 开头的标识符为私有标识符,由私有标识符定义的类元素被称为私有类元素,私有类元素只能在类中才能被访问到。类的属性、静态属性、方法、静态方法、访问器、静态访问器都可以被定义为私有类元素。示例代码如下:
class ClassA {
// 私有属性
#privateProperty;
// 静态私有属性
static #privateStaticProperty;
// 静态私有 Getter
static get #privateStaticGet() {
return 'private-static-get';
}
// 静态私有 Setter
static set #privateStaticSet(val) {
}
// 静态私有方法
static #privateStaticMethod() {
return 'private-static-method'
}
constructor(propertyValue) {
// 初始化私有属性
this.#privateProperty = propertyValue;
}
// 私有 Get
get #privateGet() {
return 'private-get'
}
// 私有 Set
set #privateSet() {
}
// 私有方法
#privateMethod() {
return 'private-method'
}
}
在类的内部可以正常访问私有类元素,在类的外部访问私有类元素会抛出句法错误。
class ClassA {
// 私有属性
#privateProperty;
constructor(property, privateProperty) {
this.property = property;
this.#privateProperty = privateProperty;
}
// 在方法中访问私有属性
getPrivateProperty() {
return this.#privateProperty;
}
}
const instance = new ClassA('property', 'private-property');
instance.property; // 'property'
instance.#privateProperty; // Uncaught SyntaxError: Private field '#privateProperty' must be declared in an enclosing class
instance.getPrivateProperty(); // 'private-property'
以上就是私有类元素的用法,它有效隔离了类内外的数据和逻辑,进一步增强了封装的效果,使程序更加健壮。
9.3 静态块
静态块提供了更加灵活的静态类元素初始化渠道,可以在静态块中使用一系列的语句来完成静态类元素的初始化。可以利用 this 在静态块中访问类的其他静态属性(包括私有属性)。
class ClassA {
// 静态属性
static staticProperty;
// 静态块初始化静态属性,捕捉错误
static {
try {
this.staticProperty = getStaticProperty();
} catch {
console.log('Error');
}
}
}
当一个类具有多个静态块时,它们会按照定义的顺序进行执行。
class ClassA {
// 静态属性 A
static staticPropertyA;
// 静态块 A
static {
this.staticPropertyA = 'static-block-a';
console.log('static-block-a');
}
// 静态属性 B
static staticPropertyB;
// 静态块 B
static {
this.staticPropertyB - 'static-block-b';
console.log('static-block-b');
}
}
// 输出
// static-block-a
// static-block-b
当一个类具有父类时,会先执行父类的静态块,再执行子类的静态块。可以利用 super
在子类的静态块中访问父类的属性。
// 父类
class ParentClass {
// 父类属性
static parentProperty;
// 父类静态块
static {
this.parentProperty = 'parent-property';
console.log('parent-static-block');
}
}
// 子类
class ChildClass extends ParentClass {
// 子类静态块
static {
console.log(super.parentProperty);
console.log('child-static-block');
}
}
// 输出
// parent-static-block
// parent-property
// child-static-block
9.4 私有 in 操作符
in
操作符可以判断实例中是否存在属性,当新增了私有化类元素后,也可以和下面例子一样,在类定义内使用 in
操作符判断私有化类元素存在与否。
class ClassA {
// 私有属性
#privateProperty;
// 利用 in 操作符判断私有属性是否存在
static hasPrivateProperty(instance) {
return #privateProperty in instance
}
constructor(privateProperty) {
this.#privateProperty = privateProperty;
}
}
const instance = new ClassA('private-property');
### 总结
阿里十分注重你对源码的理解,对你所学,所用东西的理解,对项目的理解。
![最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结](https://img-blog.csdnimg.cn/img_convert/ef336fc6eeb8c79b1e96f97e168df90a.png)
![最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结](https://img-blog.csdnimg.cn/img_convert/d3ac9c078e3063bbc4ddc4fe929112c8.png)
![最新阿里蚂蚁金服四面(已拿offer)Java技术面经总结](https://img-blog.csdnimg.cn/img_convert/04656be82d9b13ba32131bdc8ec55836.png)