一、拓展运算符在对象中使用
(1)结构赋值,只能放在最后一个参数前(且必须是个变量名,否则会报错Rest element must be last element),产生一个新对象,用于搜集尚未被读取的自身可遍历属性。
let o = {x: 1, y: 2, z: 3};
let {x, ...obj} = o;
console.log(obj) // => {y: 2, z: 3}
注意点:拓展符在解构赋值中,只能搜集自身可遍历属性。常规解构赋值,可读取原型链上的属性。
let o = Object.create({x: 1, y: 2, z: 3});
let {x, ...newObj} = o;
console.log(x, newObj) // 1, {}
(2)对象字面量中展开属性,取出对象所有自身可遍历属性,拷贝到当前对象中。<br />等同于使用Object.assign( { }, obj ) == { ...obj }<br />1、前面同名属性会被覆盖。<br />2、如果有取值函数,会先执行然后再赋值。
let a = {a :'a'},
b = {b: 'b', c: 'c'};
let obj = {...a, ...b};
console.log(obj) // => {a: "a", b: "b", c: "c"}
数组也是对象,也可以在对象中展开
let o = { ...['a', 'b', 'c'] };
console.log(o) // => {'1' : 'a', '2' : 'b', '3' : 'c'}
如果拓展运算后面是非对象类型,只有字符串会产生效果(字符串包装对象有可遍历自身属性,boolean和number类型对象没有),undefined和null不会报错(作为解构对象的时候会报错,Cannot destructure property 'x' of 'undefined')
二、Iterator 迭代器
为不同数据结构提供了统一迭代接口(统一访问机制),es6提供了Iterator接口。
1、iterator作用:
(1)提供一种遍历不同数据结构的接口
(2)能使数据结构成员按某种顺序排列
(3)提供一种新遍历方法 for … of(Iterator主要供for … of消费,for … of会主动调用Iterator接口)
2、遍历过程:
(1)创建一个指针对象,指向数据结构起始位置(迭代器本质上是一个指针对象)
(2)每次调用迭代器的next方法,会返回当前迭代信息,包括了value(当前元素的值)、done(表示遍历是否结束)
3、iterable
有些数据结构原生含有Symbol.iterator方法(遍历器生成函数),部署了iterator接口,可以直接使用for…of(object没有Symbol.iterator属性)。
原生具备Symbol.iterator属性的数据结构有:
array
arguments
nodeList
map
weakMap
set
weakSet
TypedArray
string
object本身是一种无序的数据结构,不知道哪个属性先遍历,哪个后遍历,所以没有部署遍历器接口。为对象部署遍历接口是一种线性转换,是将对象当作map结构来操作,而es6中已经提供了map结构。
如果非要用for…of来遍历对象的话,可以手动添加一个遍历器生成器函数。
let obj = {
'0' : 0,
'1' : 1,
'2' : 2,
'3' : 3,
[Symbol.iterator](){
let len = Object.keys(this).length,
index = 0,
_this = this;
return {
next(){
let res = index < len ?
{ value: _this[index++], done : false }:
{ value: undefined, done : true};
return res
}
}
}
}
for(let val of obj){
console.log(val)
}
拓展运算符用到了iterator接口