像专业人士一样解构 JavaScript 对象
你好呀!
很久以来,我一直想记录一些我目前在工作中用到的关于 JavaScript 解构概念的技巧。我觉得我学到的、并且每天都在使用的东西,一旦不再频繁使用,就会变得模糊不清。因此,我决定把这些东西写下来,这样即使不是每天都看,也能让我记住更久。我初中和高中的时候经常这样做,但大学一上来就停了,现在我感受到了这种影响,尤其是考虑到我的记忆力真的很差。
对于那些不熟悉 JavaScript 解构概念的人来说,下面是它的简要概述。如果你用 Google 一下,也会发现很多关于它的文章,所以如果你觉得这些内容太简略或不够清晰,可以自行寻找更多内容 ;)
解构并非 JavaScript 中一直存在的语言,直到 2015 年 6 月,这个概念才与其他一些特性一起被引入 JavaScript,并构成了第六版,也就是人们所熟知的 ES6 或 ES2015(点击此处查看)。
解构的初衷是为了能够以更优雅的方式基于对象属性或数组值赋值。如果你把它理解为结构化概念的反面(事实也如此),你就会明白,对象会被“分解”成多个部分,直到找到所需的值,然后用这些值创建一个变量。
检查下面的代码,它展示了在您不知道解构存在的情况下创建应该包含对象值的变量的方法之一。
注意classs
全文都要这样写,避免与关键字冲突class
。
const homoSapiens = {
kingdom: 'Animalia',
classs: 'Mammalia',
family: 'Hominidae',
genus: 'Homo',
species: 'H. sapiens'
}
const homoSapiensFamily = homoSapiens.family;
// and if you want to be certain of the type of the variable, you would
// set a default value for it in case the `family` property does not
// exist in the source object
const safeHomoSapiensFamily = homoSapiens.family || '';
您会发现,对于要在该对象中使用的每个属性,您都必须执行相同的操作,这实际上并不麻烦,但是当我们可以利用解构的强大功能来创建变量并确保其类型时,为什么还要这样做呢?
以下是使用解构来实现相同目的的代码片段。
const { family = '', species = '' } = homoSapiens;
这里我们创建了两个名为family
和species
的变量,它们基于源对象中同名的属性。并且,即使源对象中不包含这两个属性,我们也确保它们仍然是字符串。
你可能会争辩说,如果单独来看,family
和并不是真正有意义的变量名。解构还允许我们指定所需的变量名(别名),而不是使用对象中属性的名称。species
const {
family: homoSapiensFamily = '',
species: homoSapiensSpecies = ''
} = homoSapiens;
这里我们使用了和之前相同的值,但现在我们创建了两个名为homoSapiensFamily
和 的变量homoSapiensSpecies
。更有意义了吧?
如果您现在已经明白了这一点,我相信您会注意到您可以为之疯狂并解构真正的嵌套对象。
const homoSapiens = {
classs: {
name: 'Mammalia',
super: {
name: 'Tetrapoda'
},
sub: {
name: 'Theria'
}
},
species: 'H. sapiens'
};
const {
classs: {
super: {
name: homoSapiensSuperClass = ''
}
}
} = homoSapiens;
这里我们创建了一个名为的变量homoSapiensSuperClass
,其值为Tetrapoda
。
如果我们尝试解构一个嵌套对象,而我们指定的属性在某个时候不存在,该怎么办?
// considering the previous homoSapiens object
const {
classs: {
infra: {
name: homoSapiensInfraClass = ''
}
}
} = homoSapiens;
如果您尝试这样做,您会发现我们收到一条错误消息:
Uncaught TypeError: Cannot destructure property `name` of 'undefined' or 'null'.
发生这种情况是因为在源对象中,我们实际上没有infra
在该classs
对象下调用的对象。因此,该homoSapiensInfraClass
变量从未被定义。
为了避免这种情况,你可以在解构对象时为每个要处理的属性设置一个默认值。在这个特定情况下,你需要确保该infra
属性的默认值是一个对象,这样即使该属性不存在,你也能继续解构它。
const {
classs: {
infra: {
name: homoSapiensInfraClass = ''
} = {}
} = {}
} = homoSapiens;
这样,即使homoSapiens
对象不包含名为的属性,infra
您仍然会定义一个名为的变量,homoSapiensInfraClass
该变量将接收您设置的默认值,或者undefined
如果您没有为其设置默认值。
它也适用于数组!
这个想法与数组基本相同,除了语法略有不同之外,不同之处在于您不能考虑属性名称,而是根据数组中项目的顺序来执行操作。
const [first, second ] = ['a', 'b'];
// first will be 'a' and second will be 'b'
// you can also set default values
const [safeFirst = 'a', safeSecond = 'b'] = ['a']
// safeSecond here will have a value of 'b'
它也可以在函数签名中起作用!
您还可以在函数签名中进行解构,以便仅向函数上下文公开接收对象的特定属性。
const homoSapiens = {
kingdom: 'Animalia',
classs: 'Mammalia',
family: 'Hominidae',
genus: 'Homo',
species: 'H. sapiens'
}
function logSpeciesInfo ({ species = '', kingdom = '', classs = '' }) {
console.log(`The species ${species} belongs to the ${kingdom} kingdom and ${classs} class.' );
}
logSpeciesInfo(homoSapiens);
// Logs "The species H. sapiens belongs to the Animalia kingdom and Mammalia class."
函数头中未指定的对象的任何其他属性在函数主体中不存在。
我可以在任何地方进行解构吗?
MDN 网页文档的解构赋值页面中有一个很棒的表格,展示了此语法当前浏览器的兼容性。你可以看到它得到了广泛的支持,所以兼容性对你来说应该不是问题,除非……IE 对你来说是个问题 :)
测验
结合你从这篇文章学到的知识,你能运用解构的力量,在不引入任何额外变量的情况下交换两个变量的值吗?先试试再看评论;)
请在评论区留言告诉我!如果你还有其他解构的用例,也欢迎分享 :D
感谢阅读!
文章来源:https://dev.to/willamesoares/destructuring-javascript-objects-like-a-pro-17bg