我认为谷歌的 V8 团队已经等待这一刻很久了。 V8引擎(最流行的JavaScript引擎)第8版出! 这个新版本带来了一些非常好的性能改进和两个新的很酷的 JavaScript 语言特性:可选链接和无效合并。
可选链
这是一个期待已久的功能。 假设您正在与一个糟糕的 API 提供商合作。 我们将此 API 称为 CrocosAPI。 CrocosAPI 提供有关世界上所有鳄鱼的信息(这是一个不稳定的 API,每个人都知道“鳄鱼优于鳄鱼”)。
这就是我们获得鳄鱼栖息地的功能(一些鳄鱼生活在淡水、微咸水和/或咸水中)
const getWaterHabitat = async (crocName) => {
// First we call our made up api
const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName);
// We get the responses body
const crocInfo = crocResponse.body;
// We access the water property of the habitat property
return crocInfo.habitat.water;
}
// Let's get the water habitat of a crocodile called Barry
const barrysWaterHabitat = getWaterHabitat('Barry');
// this returnsbarrysWaterHabitat == ['freshwater']
现在假设 CrocosAPI 的开发人员决定改变他们的响应结构:
{
"personalInfo" : {
"firstName" : "Barry"
},
"habitat": {
"water": ["freshwater"],
}
// ... skipping
}
到:
{
"personalInfo" : {
"firstName" : "Barry"
// ...
},
// We changed 'habitat' to 'environment'
"environment": {
"water": ["freshwater"]
}
//...
}
现在如果我们调用 getWaterHabitat 我们将得到:
TypeError: Cannot read property 'water' of undefined
那是因为 crocInfo.habitat 不再存在。 现在要访问 crocInfo,我们必须访问 crocInfo.environment.water。 这意味着我们的整个应用程序将因为 CrocosAPI 的开发人员不了解版本控制而崩溃。 那么如何避免这个错误呢? 当然是可选的链接!
const getWaterHabitat = async (crocName) => {
const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName)
const crocInfo = crocResponse.body
// We access the water key with optional chaining
return crocInfo?.habitat?.water
}
const myCrocsName = 'Barry'
const barrysWaterHabitat = getWaterHabitat('Barry')
// barrysWaterHabitat == undefined
您还可以对数组使用可选索引:
const crocAddress1City = crocInfo?.personalInfo?.addresses?.[0].city // if crocInfo.personalInfo.addresses = [] // crocAddress1City === undefined
……还有功能!
// It is hard to make a short example
const getSkinStyle = (option) => {
const scales = {
color: 'green',
texture: 'shiny'
}
if (option == 'naked')
return
else
return scales
}
const crocInfo = {
name: 'Barry',
waterHabitat : 'Freshwaters',
getSkinStyle : getSkinStyle
}
const barrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
// barrysSkinColor === undefined
const larrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
// larrysSkinColor === 'green'
…并具有动态属性访问权限。 哇,真的是假期⛄🎄🎁(在撰写本文时)!
// habitatType can be "water" or "land"
const getHabitatProperty = (habitatType) => {
return crocInfo?.habitat?.[habitatType]
}
getHabitatType('water')
// returns ['freshwater']
getHabitatType('land')
// returns ['forest']
不再有类型错误,只有 undefined 值!
作为一个快速的 PSA,不要依赖可选链接作为不进行正确错误处理的借口。 我们从访问未定义值的属性中得到的 TypeError 的好处是:
- 在我们的应用程序中更容易注意到意外行为
- 它迫使我们编写更好的回退机制
在尝试访问未定义值的属性时,我们仍然应该有某种回退或警告机制。
无效合并
??... 不,我并不感到困惑,?? 是加入 && 和 || 系列的新短路运算符。 如果你写过一些 React、Vue 或 Angular,你可能已经写过或看过类似的东西。
const name = props.name || 'CrocName Error'; const age = props.age || 'Invalid Age'; const isFemale = props.isFemale || true; // pass name , age and isFemale to a view
如果不是假的,此代码将分配存储在 props.name 中的值。 如果该值是假的,则值 name 将等于 CrocName Error。
但是假设对于仍未命名的鳄鱼,API 返回一个空字符串。 在 JavaScript 中,空字符串被认为是虚假的,所以会发生这种情况:
// Let's say we have an anonymous new born boy crocodile
const props = {
name: '',
age: 0,
isFemale: false
}
const name = props.name || 'CrocName Error';
// name === 'CrocName Error'
const age = props.age || 'Invalid Age';
// age === 'Invalid Age'
const isFemale = props.isFemale || true;
// isFemale === true
这些不是我们期望的结果! 我们想将 props.name 具有 null 或 undefined 值的情况与 props.name 为空字符串的情况分开。 我们希望 age 等于 0 并且 isFemale 等于 false。 这就是 ?? 来救援的地方。
const name = '' ?? 'CrocName Error' // name === '' const age = 0 ?? 'Invalid Age'; // age === 0 const isFemale = false ?? true; // isFemale === false // Yay it worked!
|| 检查左侧运算符是否为假。 ?? 仅检查它是 null 还是 undefined。 这是给你的一个小备忘单:
// +0, -0, NaN, false, empty strings, null and undefined are all falsy false ?? true; // equals false false || true; // equals true 0 ?? 1; // equals 0 0 || 1; // equals 1 '' ?? 'default'; // equals '' '' || 'default'; // equals 'default' // null and undefined are falsy so in this case we get the same results null ?? []; // equals [] null || []; // equals [] undefined ?? []; // equals [] undefined || []; // equals []
您还可以混合运算符! 请记住使用括号。 试着想想这会做什么:
const crocName = (props.name ?? 'CrocName Error') || 'Anonymous Croc';
让我们看看几个值的结果:
props.name === 'Barry':crocName === 'Barry'props.name ===:crocName ==== 'Anonymous Croc'props.name === undefined:crocName ==== 'CrocName Error'
空值合并和可选链接一起工作
您可能已经想到了将这两个功能一起使用的很酷的方法!
const getCrocName = async (crocId) => {
// We try to access our unstable API's data
const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocId)
// If croc response or body is undefined
const crocInfo = crocResponse?.body ?? 'Croc API did not return a valid response'
// if crocResponse equals {} then crocInfo == 'Croc API did not return a valid response'
// checking if crocInfo, personal info or name is undefined/null or if name has a falsy value
return (crocInfo?.personalInfo?.name ?? 'There was a problem loading the croc\'s name') || 'Anonymous Croc'
// if crocInfo?.personalInfo?.name === '' we return 'Anonymous Croc'
// if crocInfo equals {} we return 'There was a problem loading the croc\'s name'
}
V8 V8 的性能
如今,我们被 JavaScript 的速度所宠坏,更被周期性的性能更新所宠坏。 V8 的工程师再次改进了引擎的性能和内存。 如果您有兴趣了解更多信息,可以查看 他们的发布帖子 。 我喜欢这些更新的一点是它提高了我们的代码性能,但我们不必编写任何新内容!
小红利
要检查是否可以在 Node.jd 中使用 V8 v8,您可以运行 node -p process.versions.v8 并查看版本是否超过 8。 现在你应该在 web 上使用像 core-js 这样的 polyfill 和/或转译器。 如果你使用 Babel,可以使用 @babel/plugin-proposal-optional-chaining、@babel/plugin-proposal-nullish-coalescing-operator。
祝您假期愉快! 🎄🎉