仅仅使用 const { couple } = avengers; 并没有办法提取出 couple 的值。只有把要提取的对象属性的 位置和名称映射出来,JS 编译器才能得到相应的信息,沿着对象的所有属性往下查找,并准确地提取我们想要的值。
这里也要注意到 couple 用了语法捷径给变量命名,实际上是这样的:
const { ironManCharacters: { couple: couple } } = avengers;
couple 就是这样被定义的,它的值就是对象 avengers 中属性名为 couple 的值。
给对象的属性解构赋值
到目前为止,我们都是解构对象的值来给单个的变量赋值,其实还可以给另一个对象的属性赋值。
const avengers = { blackWidow: 'Natasha Romanoff', ironManCharacters: { couple: { ironMan: 'Tony Stark', hera: 'Pepper Potts' } } }; const ironManProperties = { family: {} }; ({ ironManCharacters: { couple: ironManProperties.family } } = avengers); ironManProperties.family // ironManProperties.family = { // ironMan: 'Tony Stark', // hera: 'Pepper Potts' // } // Output ironManProperties.family: ironManProperties.family;
在这里我们把 ironManCharacters.couple 的值赋给了 ironManProperties.family 这个属性,这里有两点需要说明一下:
1.解构赋值必须被包含在 圆括号 内
当我们在对一个已存在的变量(如上面例子中的 ironManProperties)进行解构时,一定要这样做,而不是去声明一个新的变量。
2.模式仍然相匹配
{ ironManCharacters: { couple... } } 与对象 avengers 中的 ironManCharacters 相匹配。这样就能如你所愿,从 avengers 对象中提取出 ironManCharacters.couple 的值了。但是现在,couple 后面放置了一个新的对象ironManProperties 和它的属性 family,其实被赋值的就是这个对象的属性ironManProperties.family了。
当你尝试把这种情况解释清楚时,是否还有所困惑呢?在jsfiddle里面尝试上面的代码,一切就明了了。
如果你不清楚自己为什么要这样做,请参考下一篇文章的例子。这些例子会告诉你,为什么采用这种模式来解构API调用的 JSON 对象,让你领略解构的神奇之处!
默认值
解构时,你还可以给变量指定一个默认值:
// Setup our object const avengers = { ironMan: 'Tony Stark', cap: 'Steve Rogers', blackWidow: 'Natasha Romanoff' }; // Destructure using defaults const { ironMan, cap, blackWidow, theHulk='Bruce Banner' } = avengers; // ironMan = 'Tony Stark' // cap = 'Steve Rogers' // blackWidow = 'Natasha Romanoff' // theHulk = 'Bruce Banner' // Output blackWidow: blackWidow;
解构时要避免出现这些问题
解构赋值时没有使用 const, let, var
在讲到对 对象属性 进行解构赋值时就已经提及了这一点,但这里还是有必要再重申一下,让大家有个深刻的印象。
不能对已经声明的变量进行解构
也就是说,你只能在对变量解构赋值的同时声明变量。
// Setup our object const avengers = { ironMan: 'Tony Stark', cap: 'Steve Rogers', blackWidow: 'Natasha Romanoff', theHulk: 'Bruce Banner' }; // Valid destructuring const { ironMan } = avengers; let { cap } = avengers; var { blackWidow } = avengers; // Invalid destructuring let theHulk; { theHulk } = avengers; // Error // Output theHulk: theHulk;
为何不能对一个已经声明的变量进行解构呢?那是因为这时如果你使用了花括号 { ,JavaScript会认为你是在声明一个 block。
解决的办法就是把整个解构赋值用一对 圆括号 括起来。
如何对一个已声明的变量进行解构赋值
// Setup our object const avengers = { ironMan: 'Tony Stark', cap: 'Steve Rogers', blackWidow: 'Natasha Romanoff', theHulk: 'Bruce Banner' }; // A valid Hulk let theHulk; ({ theHulk } = avengers); // theHulk = 'Bruce Banner' // Output theHulk: theHulk;
现在我们不是以花括号开头,所以JS不会认为我们是在声明一个 block ,这样就可以达到预期的解构结果。
直接返回一个被解构的值
在没有先声明一个接下来要被返回的变量时,就直接返回一个被解构的值,这样是无法达到预期效果的。例如,下面的代码中,返回的将是整个 ironMan对象,而不是预期要的值 Tony Stark。
// Note: this doesn't work! function getTonyStark(avengers){ return { ironMan: { realName } } = avengers; // return the avengers object, not the realName value } const avengers = { ironMan: { realName: 'Tony Stark' } }; const tonyStark = getTonyStark(avengers); // tonyStark = { // ironMan: { // realName: 'Tony Stark' // } // }; // Output tonyStark: tonyStark;
要从一个被解构的对象中提取值,必须先把它赋值给一个变量,然后再把这个变量返回,如下代码所示: