Skip to content

Latest commit

 

History

History
158 lines (105 loc) · 4.19 KB

10.5.md

File metadata and controls

158 lines (105 loc) · 4.19 KB

10.5 如果有一部分没有匹配上

解构过程中如果要获取的目标在源上不存在,此时的处理方式与 JavaScript 处理不存在的属性和数组元素一样:内部相应部分匹配上 undefined 。如果该内部部分是一个变量,意味着这个变量会被设为 undefined

let [x] = []; // x = undefined
let {prop:y} = {}; // y = undefined

记住:如果去匹配 undefined ,对象模式和数组模式都会抛出 TypeError 异常。

10.5.1 默认值

默认值是模式的一个特性:如果某个部分(一个对象属性或者一个数组元素)在源里面没有匹配的内容,它会得到:

  • 它的默认值(如果指定了默认值)
  • undefined(否则)

也就是说,提供默认值是可选的。

让我们看一个例子。在下面的解构过程中,第0个元素在右侧没有匹配上。因此, x 对应上3,解构过程继续,最终导致 x 的值被设为3。

let [x=3, y] = []; // x = 3; y = undefined

也可以在对象模式中使用默认值:

let {foo: x=3, bar: y} = {}; // x = 3; y = undefined

10.5.1.1 undefined 使默认值生效

当某个部分没有匹配或者匹配上的是 undefined ,就会使用默认值:

let [x=1] = [undefined]; // x = 1
let {prop: y=2} = {prop: undefined}; // y = 2

此现象的原理将会在下一章阐述,在《默认参数》那一节。

10.5.1.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()

10.5.1.3 默认值可以指向模式中其它变量

默认值可以指向任何变量,包括在同一个模式中的另一个变量:

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

但是,顺序很重要:变量 xy 由左向右依次声明,如果在声明之前访问的话,就会产生一个 ReferenceError 异常:

let [x=y, y=3] = []; // ReferenceError

10.5.1.4 模式的默认值

到目前为止,我们值看到变量的默认值,也可以给模式设定默认值:

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

仍然感到迷惑
后面有个章节从算法角度解释了解构过程,这将会给你一个另外的视角。