我认为谷歌的V8团队一直在等待这个时刻很长一段时间。V8引擎(https://andsky.com/tech/tutorials/js-v8-engine)(最受欢迎的JavaScript引擎)的第8版已经发布了!这个新版本带来了一些非常好的性能改进和两种新的JavaScript语言功能:可选链接和无连接。
选择链接
假设你正在与一个可怕的API提供商合作,让我们把这个API称为CrocosAPI。CrocosAPI提供了关于世界上所有的鳄鱼的信息(这是一个不稳定的API,每个人都知道捕食者比鳄鱼更出色
。
这就是我们获得鳄鱼的栖息地的功能(有些鳄鱼生活在淡水,淡水和/或盐水中)
1const getWaterHabitat = async (crocName) => {
2 // First we call our made up api
3 const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName);
4 // We get the responses body
5 const crocInfo = crocResponse.body;
6 // We access the water property of the habitat property
7 return crocInfo.habitat.water;
8}
9
10// Let's get the water habitat of a crocodile called Barry
11const barrysWaterHabitat = getWaterHabitat('Barry');
12// this returnsbarrysWaterHabitat == ['freshwater']
现在,假设CrocosAPI的开发者决定改变他们的响应的结构:
1{
2 "personalInfo" : {
3 "firstName" : "Barry"
4 },
5 "habitat": {
6 "water": ["freshwater"],
7 }
8 // ... skipping
9}
二:
1{
2 "personalInfo" : {
3 "firstName" : "Barry"
4 // ...
5 },
6 // We changed 'habitat' to 'environment'
7 "environment": {
8 "water": ["freshwater"]
9 }
10 //...
11}
现在,如果我们叫getWaterHabitat
,我们将得到:
1TypeError: Cannot read property 'water' of undefined
这是因为crocInfo.habitat
不再存在,现在要访问crocInfo
,我们必须访问crocInfo.environment.water
。这意味着我们的整个应用程序会崩溃,只是因为CrocosAPI的开发人员不知道版本。
1const getWaterHabitat = async (crocName) => {
2 const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName)
3 const crocInfo = crocResponse.body
4 // We access the water key with optional chaining
5 return crocInfo?.habitat?.water
6}
7
8const myCrocsName = 'Barry'
9const barrysWaterHabitat = getWaterHabitat('Barry')
10// barrysWaterHabitat == undefined
您还可以使用可选的数组索引:
1const crocAddress1City = crocInfo?.personalInfo?.addresses?.[0].city
2// if crocInfo.personalInfo.addresses = []
3// crocAddress1City === undefined
...和功能!
1// It is hard to make a short example
2const getSkinStyle = (option) => {
3 const scales = {
4 color: 'green',
5 texture: 'shiny'
6 }
7 if (option == 'naked')
8 return
9 else
10 return scales
11}
12
13const crocInfo = {
14 name: 'Barry',
15 waterHabitat : 'Freshwaters',
16 getSkinStyle : getSkinStyle
17}
18
19const barrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
20// barrysSkinColor === undefined
21const larrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
22// larrysSkinColor === 'green'
...和动态的财产接入,哇,这是真正的假期 (在写作时)!
1// habitatType can be "water" or "land"
2const getHabitatProperty = (habitatType) => {
3 return crocInfo?.habitat?.[habitatType]
4}
5getHabitatType('water')
6// returns ['freshwater']
7getHabitatType('land')
8// returns ['forest']
没有更多的输入错误,只是一个未定义
的值!
作为一个快速的PSA,不要依靠可选的链作为一个借口来不做正确的错误处理.我们从访问未定义值的属性中获得的TypeError的好处是:
- 更容易在我们的应用程序中注意到意想不到的行为
- 它迫使我们写出更好的反馈机制
当我们试图访问未定义值的属性时,我们仍然应该有某种反弹或警告机制。
零组合
??
... 不,我不困惑, ??
是新的短路操作员,加入了 &&
和 Átha Cliath
家族. 如果你写了一些 React、Vue 或 Angular,你可能已经写过或看到了类似的东西。
1const name = props.name || 'CrocName Error';
2const age = props.age || 'Invalid Age';
3const isFemale = props.isFemale || true;
4// pass name , age and isFemale to a view
此代码将分配存储在 props.name
中的值,如果值不是假的,则值 name
将等于 CrocName Error
。
但是,假设对于尚未命名的鳄鱼,API会返回一个空字符串,在JavaScript中,空字符串被认为是假的,所以这会发生:
1// Let's say we have an anonymous new born boy crocodile
2const props = {
3 name: '',
4 age: 0,
5 isFemale: false
6}
7
8const name = props.name || 'CrocName Error';
9// name === 'CrocName Error'
10
11const age = props.age || 'Invalid Age';
12// age === 'Invalid Age'
13
14const isFemale = props.isFemale || true;
15// isFemale === true
这些不是我们所期望的结果! 我们希望将props.name
具有null
或undefined
值的场景分开到props.name
是一个空串的情况下。
1const name = '' ?? 'CrocName Error'
2// name === ''
3
4const age = 0 ?? 'Invalid Age';
5// age === 0
6
7const isFemale = false ?? true;
8// isFemale === false
9
10// Yay it worked!
检查左侧操作员是否是假的。
只检查它是否是null
或undefined
。
1// +0, -0, NaN, false, empty strings, null and undefined are all falsy
2false ?? true; // equals false
3false || true; // equals true
4
50 ?? 1; // equals 0
60 || 1; // equals 1
7
8'' ?? 'default'; // equals ''
9'' || 'default'; // equals 'default'
10
11// null and undefined are falsy so in this case we get the same results
12null ?? []; // equals []
13null || []; // equals []
14
15undefined ?? []; // equals []
16undefined || []; // equals []
您也可以混合操作员! 只需记住使用笔记本。 试着想想这会做什么:
1const crocName = (props.name ?? 'CrocName Error') || 'Anonymous Croc';
让我们看看几个值的结果:
props.name === 'Barry'
:crocName === 'Barry'
props.name === ''
:crocName ==== 'Anonymous Croc'
props.name === undefined
:crocName ==== 'CrocName Error'
零合并和可选链一起工作
你可能已经考虑了使用这两种功能的酷方法!
1const getCrocName = async (crocId) => {
2 // We try to access our unstable API's data
3 const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocId)
4 // If croc response or body is undefined
5 const crocInfo = crocResponse?.body ?? 'Croc API did not return a valid response'
6 // if crocResponse equals {} then crocInfo == 'Croc API did not return a valid response'
7
8 // checking if crocInfo, personal info or name is undefined/null or if name has a falsy value
9 return (crocInfo?.personalInfo?.name ?? 'There was a problem loading the croc\'s name') || 'Anonymous Croc'
10 // if crocInfo?.personalInfo?.name === '' we return 'Anonymous Croc'
11 // if crocInfo equals {} we return 'There was a problem loading the croc\'s name'
12}
V8 的性能
如今,我们对JavaScript的速度感到困惑,而且由于反复的性能更新而更加困扰。 再一次,V8的工程师改进了其引擎的性能和内存。 如果您对如何了解更多信息感兴趣,您可以查看他们的发布帖子(https://v8.dev/blog/v8-release-80)。
小奖金
要检查你是否可以在 Node.jd 中使用 V8 v8,你可以运行node -p process.versions.v8
并查看版本是否已完成 8. 现在你应该在网络上使用像 core-js这样的多元化文件和/或传输器。 如果你正在使用 Babel, @babel/plugin-proposal-optional-chaining
, @babel/plugin-proposal-nullish-coalescing-operator
可用。
快乐快乐的假期!