解构过程中如果要获取的目标在源上不存在,此时的处理方式与 JavaScript 处理不存在的属性和数组元素一样:内部相应部分匹配上 undefined
。如果该内部部分是一个变量,意味着这个变量会被设为 undefined
:
let [x] = []; // x = undefined
let {prop:y} = {}; // y = undefined
记住:如果去匹配 undefined
,对象模式和数组模式都会抛出 TypeError
异常。
默认值是模式的一个特性:如果某个部分(一个对象属性或者一个数组元素)在源里面没有匹配的内容,它会得到:
- 它的默认值(如果指定了默认值)
- undefined(否则)
也就是说,提供默认值是可选的。
让我们看一个例子。在下面的解构过程中,第0个元素在右侧没有匹配上。因此, x
对应上3,解构过程继续,最终导致 x
的值被设为3。
let [x=3, y] = []; // x = 3; y = undefined
也可以在对象模式中使用默认值:
let {foo: x=3, bar: y} = {}; // x = 3; y = undefined
当某个部分没有匹配或者匹配上的是 undefined
,就会使用默认值:
let [x=1] = [undefined]; // x = 1
let {prop: y=2} = {prop: undefined}; // y = 2
此现象的原理将会在下一章阐述,在《默认参数》那一节。
默认值本身在需要的时候计算。换句话说,下面的解构:
let {prop: y=someFunc()} = someValue;
等同于:
let y;
if (someValue.prop === undefined) {
y = someFunc();
} else {
y = someValue.prop;
}
可以通过 console.log()
来观测到这个过程:
> function log(x) { console.log(x); return 'YES' }
> let [a=log('hello')] = [];
hello
> a
'YES'
> let [b=log('hello')] = [123];
> b
123
在第二个解构过程中,默认值没有被触发,所以没有调用 log()
。
默认值可以指向任何变量,包括在同一个模式中的另一个变量:
let [x=3, y=x] = []; // x=3; y=3
let [x=3, y=x] = [7]; // x=7; y=7
let [x=3, y=x] = [7, 2]; // x=7; y=2
但是,顺序很重要:变量 x
和 y
由左向右依次声明,如果在声明之前访问的话,就会产生一个 ReferenceError
异常:
let [x=y, y=3] = []; // ReferenceError
到目前为止,我们值看到变量的默认值,也可以给模式设定默认值:
let [{ prop: x } = {}] = [];
这意味着什么?回忆一下默认值的规则:
如果模式中某部分在源中没有匹配,将会使用默认值[...],解构过程继续。
上面的例子中,在索引0处的元素没有匹配,解构过程进入如下步骤:
let { prop: x } = {}; // x = undefined
你可以把模式 { prop: x }
替换成变量 pattern
来更容易地看出为什么会这样:
let [pattern = {}] = [];
更复杂的默认值。让我们更深入地探索模式的默认值。在下面的例子中,我们通过默认值 { prop: 123 }
给 x
赋上一个值:
let [{ prop: x } = { prop: 123 }] = [];
因为在索引为0处的数组元素在右侧没有相应匹配,解构过程以如下所示的形式继续,并且 x
的值被设为123。
let { prop: x } = { prop: 123 }; // x = 123
然而,如果右侧在索引0处有一个元素, x
将不会以这种方式被赋上一个值,因为并没有触发默认值。
let [{ prop: x } = { prop: 123 }] = [{}];
这种情形下,解构过程像下面这样继续:
let { prop: x } = {}; // x = undefined
因此,如果想在对象或者属性不存在的时候,让 x
被赋上值123,需要为 x
自身指定上默认值:
let [{ prop: x=123 } = {}] = [{}];
在这里,解构过程像下面这样继续,不管右侧是 [{}]
,还是 []
。
let { prop: x=123 } = {}; // x = 123
仍然感到迷惑
后面有个章节从算法角度解释了解构过程,这将会给你一个另外的视角。