在赋值中 pattern = someValue
, pattern
是如何获取 someValue
内部的数据的?
在获取属性之前,对象模式将源解构成对象。这意味着解构对原始值也有效:
let {length : len} = 'abc'; // len = 3
let {toString: s} = 123; // s = Number.prototype.toString
转换成对象的过程不是通过 Object()
的,而是通过内部的 ToObject() 操作。 Object()
从不失败:
> typeof Object('abc')
'object'
> var obj = {};
> Object(obj) === obj
true
> Object(undefined)
{}
> Object(null)
{}
如果转换目标是 undefined
或者 null
,则 ToObject()
会抛出一个 TypeError
异常。因此,下面的解构过程在获取属性之前就失败了:
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
因此,可以使用空的对象模式 {}
去检测一个值在解构过程中是否可转换成一个对象。就像上面看见的,仅 undefined
和 null
不能转换:
({} = [true, false]); // OK, Arrays are coercible to objects
({} = 'abc'); // OK, strings are coercible to objects
({} = undefined); // TypeError
({} = null); // TypeError
表达式两侧的括号是必要的,因为在 JavaScript 中语句不能以大括号开始。
数组解构使用迭代器获取源的元素。因此,可以用数组的方式解构任何一个可迭代的值。让我们看一看可迭代的值的示例。
字符串是可迭代的:
let [x,...y] = 'abc'; // x='a'; y=['b', 'c']
别忘了,字符串的迭代器返回代码点( code points )(“ Unicode 字符”,21位),而不是代码单元(“ JavaScript 字符”,16位)。(更多关于 Unicode 的信息,参考“ Speaking JavaScript ”的“ Chapter 24. Unicode and JavaScript ”章)例如:
let [x,y,z] = 'a\uD83D\uDCA9c'; // x='a'; y='\uD83D\uDCA9'; z='c'
不能通过索引下标获取一个 Set 集合的元素,但是可以通过迭代器获取。因为,数组解构对 Set 有效:
let [x,y] = new Set(['a', 'b']); // x='a'; y='b’;
Set
迭代器返回元素的顺序与元素插入的顺序一致,这就是为什么上述的解构结果总是一样的。
无穷序列。解构同样对无穷序列有效。生成器函数 allNaturalNumbers()
返回一个迭代器,生成0,1,2,...。
function* allNaturalNumbers() {
for (let n = 0; ; n++) {
yield n;
}
}
下面的解构获取该无穷序列前面的三个元素。
let [x, y, z] = allNaturalNumbers(); // x=0; y=1; z=2
如果一个值有一个方法,该方法有一个键是 Symbol.iterator
,键值是一个对象,那么该值就是可迭代的。如果要解构的对象不可迭代,那么数组解构时就会抛出 TypeError
错误:
let x;
[x] = [true, false]; // OK, Arrays are iterable
[x] = 'abc'; // OK, strings are iterable
[x] = { * [Symbol.iterator]() { yield 1 } }; // OK, iterable
[x] = {}; // TypeError, empty objects are not iterable
[x] = undefined; // TypeError, not iterable
[x] = null; // TypeError, not iterable
在获取迭代元素之前 TypeError
异常就会抛出,这意味着可以使用空的数组模式 []
来检查一个值是否可迭代:
[] = {}; // TypeError, empty objects are not iterable
[] = undefined; // TypeError, not iterable
[] = null; // TypeError, not iterable