Symbol.iterator
ES6中内置了一些Symbol,其中最重要的一个恐怕就是Symbol.iterator了,相当于迭代器的接口,只有对象里有这个symbol的属性,才可以认为此对象是可迭代的。
ES6新增了两个协议:
可迭代协议:对象必须具有Symbol.Iterator属性,属性值为一个函数,当这个对象被迭代时,就会调用该函数,返回一个迭代器。
迭代器协议:描述了迭代器对象的具体规则。
1.JS中哪些对象里实现了这个接口呢?常见的有Array,String,arguments,还有后面高级的数据结构,如Set,Map等
console.log(''[Symbol.iterator]);//[Symbol.iterator]()
console.log([][Symbol.iterator]);//values()
console.log(2[Symbol.iterator]);//underfined
new Map()[Symbol.iterator] //entries()
new Set()[Symbol.iterator] //values()
// 对象没有iterator接口
console.log({}[Symbol.iterator]());//Uncaught TypeError: [Symbol.iterator] is not a function
2.迭代器
在Js中迭代器对象实现了可迭代协议,迭代器对象由Symbol.iterator属性的值返回。
Symbol.iterator属性的值是一个函数,它返回一个迭代器对象。
迭代器指的是拥有next方法的对象。
该next方法必须返回一个带有value和done的对象。
3.哪里会用呢?
(1) 解构赋值
(2)扩展运算符
(3)yield*
(4)Array.form()
(5)for…of
(6)Map()、Set()、WeakMap()、WeakSet() //例如:new Map([[‘a’,1],[‘b’,2]])
const obj={
[Symbol.iterator](){
let index=0;
let arr=Object.keys(this);
return {
next(){
if(index<4){
return {
'value':arr[index++],
'done':false
}
}
return {
'value':'',
'done':true
}
}
}
},
'a':1,
'b':2,
'c':3,
'd':4
}
let [x,y]=obj
console.log(x,y) //a b
console.log([...obj]) //["a", "b", "c", "d"]
let gen=function* (){
yield 'start';
yield* obj;
yield 'end';
}
console.log([...gen()]) //["start", "a", "b", "c", "d", "end"]
console.log(Array.from(obj)) //["a", "b", "c", "d"]
for(let i of obj){
console.log(i) //a b c d
}
es6循环方式对比
1.for循环.
优点:效率高.
缺点:写法太麻烦,对map,set这种不好循环.
2.forEach、map、filter…
优点:写法简单,语义化强
缺点:只对每一项执行回掉,不能break,return跳出循环
3.for…in
优点:可以用来遍历对象
缺点:会遍历手动添加的键,甚至原型链上的;输出不固定
如果迭代的对象的变量值是null或者undefined, for in不执行循环体
4.for…of
for…of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
优点:可以遍历所有数据结构;避免了for in的所有缺点,可以使用break,continue和return
缺点:可以break,return,contanue;不适用于处理原有的原生对象(原生对象是一个子集,包含一些在运动过程中动态创建的对象)