ECMAScript 2024(ES11) 的新特性总结(2)

const x = a?.b ?? 0;

下面介绍下ES11新增的可选链操作符(?.

3、可选链接


当我们需要尝试访问某个对象中的属性或方法而又不确定该对象是否存在时,该语法可以极大的简化我们的代码,比如下面这种情况:

const el = document.querySelector(“.class-a”)

const height = el.clientHeight

当我们并不知道页面中是否真的有一个类名为 class-a 的元素,因此在访问clientHeight之前为了防止bug产生需要先进行一些判断:

const height = el ? el.clientHeight : undefined

上面的写法虽然可以实现,但是的确有人会觉得麻烦,而使用「可选链操作符」 ,就可以将代码简化成如下形式:

const height = el?.clientHeight

下面介绍常用的使用场景:

属性访问

需要获取某个对象中的属性,就都可以使用该语法:

a?.b

a?.[x]

上面的代码中,如果 a 为undefinednull,则表达式会立即返回undefined,否则返回所访问属性的值。也就是说,它们与下面这段代码是等价的:

a == null ? undefined : a.b

a == null ? undefined : a[x]

方法调用

在尝试调用某个方法时,也可以使用该语法:

a?.()

同样是如果 a 为undefinednull,则返回undefined,否则将调用该方法。不过需要额外注意的是,该操作符并不会判断 a 是否是函数类型,因此如果 a 是一个其它类型的值,那么这段代码依然会在运行时抛出异常。

访问深层次属性

在访问某个对象较深层级的属性时,也可以串联使用该操作符:

a?.b?.[0]?.()?.d

可能有人会懒得先去判断是否真的有必要,就给访问链路中的每个属性都加上该操作符。但类似上面代码中所展示的那样,这种代码可读性比较差。而且若真的有一个应当存在的对象因为某些 bug 导致它没有存在,那么在访问它时就应当是抛出异常,这样可以及时发现问题,而不是使它被隐藏起来。建议只在必要的时候才使用可选链操作符

4、BigInt


在 ES 中,所有 Number 类型的值都使用 64 位浮点数格式存储,因此 Number 类型可以有效表示的最大整数为 2^53。而使用新的 BigInt 类型,可以操作任意精度的整数。

有两种使用方式:1、在数字字面量的后面添加后缀n;2、使用其构造函数BigInt

const bigInt = 9007199254740993n

const bigInt = BigInt(9007199254740992)

// 在超过 Number 最大整数限制时,我们也可以改为传入一个可能被正确解析的字符串

const bigInt = BigInt(‘9007199254740993’)

和 Number 类似,BigInt 也支持+-、、**%运算符:

3n + 2n // => 5n

3n 2n // => 6n

3n 2n // => 9n

3n % 2n // => 1n

但因为 BigInt 是纯粹的整数类型,无法表示小数位,因此 BigInt 的除法运算(/)的结果值依然还是一个整数,即向下取整:

const bigInt = 3n;

bigInt / 2n; // => 1n,而不是 1.5n

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样也位支持位运算符,除了无符号右移运算符:

1n & 3n // => 1n

1n | 3n // => 3n

1n ^ 3n // => 2n

~1n // => -2n

1n << 3n // => 8n

1n >> 3n // => 0n

1n >>> 3n // Uncaught TypeError: BigInts have no unsigned right shift, use >> instead

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

BigInt 可以和字符串之间使用+运算符连接

1n + ’ Number’ // => 1 Number

'Number ’ + 2n // => Number 2

下面这些场景不支持使用BigInt:

1、BigInt 无法和 Number 一起运算,会抛出类型异常

1n + 1

// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

2、一些内置模块如 Math 也不支持 BigInt,同样会抛出异常

Math.pow(2n, 64n)

// Uncaught TypeError: Cannot convert a BigInt value to a number

3、BigInt 和 Number 相等,但并不严格相等,但他们之间可以比较大小

1n 1 // => true

1n = 1 // => false

但他们之间是可以比较大小的:

1n < 2 // => true

1n < 1 // => false

2n > 1 // => true

2n > 2 // => false

而且在转换为 Boolean 值时,也和 Number 一样,0n 转为 false,其它值转为 true

!!0n // => false

!!1n // => true

另外两者之间只能使用对方的构造函数进行转换:

Number(1n) // => 1

BigInt(1) // => 1n

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但两者之间的转换也都有一些边界问题:

// 当 BigInt 值的精度超出 Number 类型可表示的范围时,会出现精度丢失的问题

Number(9007199254740993n)

// => 9007199254740992

// 当 Number 值中有小数位时,BigInt 会抛出异常

BigInt(1.1)

// VM4854:1 Uncaught RangeError: The number 1.1 cannot be converted to a BigInt because it is not an integer

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配套地,在类型化数组中也提供了与 BigInt 对应的两个数组类型:BigInt64ArrayBigUint64Array

const array = new BigInt64Array(4);

array[0] // => 0n

array[0] = 2n

array[0] // => 2n

但因为每个元素限定只有 64 位,因此即便使用无符号类型,最大也只能表示 2^64 - 1:

const array = new BigUint64Array(4);

array[0] = 2n 64n

array[0] // => 0n

array[0] = 2n ** 64n - 1n

array[0] // => 18446744073709551615n

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5、globalThis


浏览器:window、worker:self、node:global

在浏览器环境中,我们可以有多种方式访问到全局对象,最常用到的肯定是 window,但除此之外还有 self,以及在特殊场景下使用的 framesparaent 以及 top

我们通常不怎么需要关心 windowself 之间的区别,但如果使用 Web Worker,那就应当了解 window 是只在主线程中才有的全局属性,在 Worker 线程中,我们需要改为使用 self

而在 node.js 环境中,我们需要使用 global,至于像 JSC.js 这种更小众的环境中,则需要使用 this

在一般的开发工作中,可能很少需要访问全局环境,而且大多时候也只需要基于一种环境进行开发,所以不太需要处理这种麻烦的问题。但是对于 es6-shim 这种需要支持多种环境的基础库来说,它们需要解决这个问题。

早先,我们可以通过下面这段代码较为方便地拿到全局对象:

const globals = (new Function(‘return this;’))()

但受到 Chrome APP 内容安全策略的影响(为缓解跨站脚本攻击的问题,该政策要求禁止使用 eval 及相关的功能),上面这段代码将无法在 Chrome APP 的运行环境中正常执行。

无奈之下,像 es6-shim 这种库就只能穷举所有可能的全局属性

var getGlobal = function () {

// the only reliable means to get the global object is

// Function('return this')()

// However, this causes CSP violations in Chrome apps.

if (typeof self ! ‘undefined’) { return self; }

if (typeof window ! ‘undefined’) { return window; }

if (typeof global ! ‘undefined’) { return global; }

throw new Error(‘unable to locate global object’);

};

var globals = getGlobal();

if (!globals.Reflect) {

defineProperty(globals, ‘Reflect’, {}, true);

}

这种问题等真的遇到了,每次处理起来也是很麻烦的。所以才有了这次提案中的 globalThis

通过 globalThis,我们终于可以使用一种标准的方法拿到全局对象,而不用关心代码的运行环境。对于 es6-shim 这种库来说,这是一个极大的便利特性:

if (!globalThis.Reflect) {

defineProperty(globalThis, ‘Reflect’, {}, true);

}

另外,关于 globalThis 还有一些细节的问题,比如为满足 Secure ECMAScript 的要求,globalThis 是可写的。而在浏览器页面中,受到 outer window 特性的影响,globalThis 实际指向的是 WindowProxy,而不是当前页面内真实的全局对象(该对象不能被直接访问)。

6、Promise.allSettled


Promise上有提供一组组合方法(比如最常用到的 Promise.all),它们都是接收多个 promise 对象,并返回一个表示组合结果的新的 promise,依据所传入 promise 的结果状态,组合后的 promise 将切换为不同的状态。

目前为止这类方法一共有如下四个,这四个方法之间仅有判断逻辑上的区别,也都有各自所适用的场景:

  • Promise.all 返回一个组合后的 promise,当所有 promise 全部切换为 fulfilled 状态后,该 promise 切换为 fulfilled 状态;但若有任意一个 promise 切换为 rejected 状态,该 promise 将立即切换为 rejected 状态;

  • Promise.race 返回一个组合后的 promise,当 promise 中有任意一个切换为 fulfilledrejected 状态时,该 promise 将立即切换为相同状态;

  • Promise.allSettled 返回一个组合后的 promise,当所有 promise 全部切换为 fulfilledrejected 状态时,该 promise 将切换为 fulfilled 状态;

  • Promise.any 返回一个组合后的 promise,当 promise 中有任意一个切换为 fulfilled 状态时,该 promise 将立即切换为 fulfilled 状态,但只有所有 promise 全部切换为 rejected 状态时,该 promise 才切换为 rejected 状态。_(_ECMAScript2021

Promise.allSettled用法:

传入一个数组,里面放任意多个 promise 对象,并接受一个表示组合结果的新的 promise。

需要注意的是,组合后的 promise 会等待所有所传入的 promise,当它们全部切换状态后(无论是 fulfilled 状态 还是 rejected 状态),这个组合后的 promise 会切换到 fulfilled 状态并给出所有 promise 的结果信息:

async function a() {

const promiseA = fetch(’/api/a’) // => rejected, <Error: a>

const promiseB = fetch(’/api/B’) // => fulfilled, “b”

const results = await Promise.allSettled([ promiseA, promiseB])

results.length // => 3

results[0] // => { status: “rejected”, reason: <Error: a> }

results[1] // => { status: “fulfilled”, value: “b” }

}

因为结果值是一个数组,所以你可以很容易地过滤出任何你感兴趣的结果信息:

// 获取所有 fulfilled 状态的结果信息

results.filter( result => result.status = “fulfilled” )

// 获取所有 rejected 状态的结果信息

results.filter( result => result.status = “rejected” )

// 获取第一个 rejected 状态的结果信息

results.find( result => result.status = “rejected” )

使用场景如下:

1、有时候在进行一个页面的初始化流程时,需要加载多份初始化数据,或执行一些其它初始化操作,而且通常会希望等待这些初始化操作全部完成之后再执行后续流程:

async function init() {

setInited(false)

setInitError(undefined)

const results = await Promise.allSettled([

loadDetail(),

loadRecommentListFirstPage(),

initSDK(),

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
tail(),

loadRecommentListFirstPage(),

initSDK(),

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-el0e14xC-1715348185759)]

[外链图片转存中…(img-J3b0r0Sx-1715348185759)]

[外链图片转存中…(img-ks1FwA0c-1715348185759)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值