1. 什么是迭代器
迭代器是统一的接口,它是一个对象,对象里面有next方法,每次调用这个方法就会输出数据结构的成员。第一次输出第一个成员,第二次输出第二个成员,以此类推。输出成员的形式为:{value:值,done:true/false}。注意:done中的true表明当前循环完成了,false表明当前循环没有完成。
2. 为什么要使用迭代器
- 在没有使用迭代器之前,我们可以使用for循环来打印数组中的元素。
缺点:a.理解方面比较差;b.for中i的这个变量不好管理。
- 在没有使用迭代器之前,我们可以使用forEach方法来打印数组中的元素。
缺点:不能跳出循环,在forEach中使用break或者continue会报错。因为forEach是从头循环到尾,中间是不能有中断的。
- 在没有使用迭代器之前,我们可以使用for in来打印数组中的元素。
缺点:a.理解方面比较差;b.会循环出来不是我们数组中的索引的属性。
什么是不是我们数组中的索引的属性,下面来举一个例子说明一下:
1 2 3 4 5 6 7 8 9 10
| let names = ["xiaoming","xiaohong","xiaoli"]; names.age = 18; for(var name in names){ console.log(names[name]); }
|
此时你会发现你本意只是想把names数组中的那三个值打印出来,但是却发现你添加的age中的值18被打印出来了,与我们预期所期望的不符合。
3. 自己写一个迭代器
根据迭代器的特性,自己手写了一个迭代器的例子,代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let names = ["xiaoming","xiaohong","xiaoli"]; function createIterator(arr){ var index = 0; return{ next(){ return index < arr.length ? {value: arr[index++],done: false} : {value: undefined,done: true}; } } } let iterator = createIterator(names); iterator.next(); iterator.next(); iterator.next(); iterator.next();
|
4. 默认迭代器
4.1 数组迭代器(内置方法)
1 2 3 4
| let names = ["xiaoming","xiaohong","xiaoli"]; console.log(names[Symbol.iterator]);
console.log(names[Symbol.iterator]());
|
4.2 类数组迭代器(内置方法)
1 2 3 4 5 6
| let argsIt; function fn(a,b,c){ argsIt = arguments[Symbol.iterator](); } fn(1,2,3); console.log(argsIt);
|
4.3 字符串迭代器(内置方法)
1 2
| let str = "daipi173"; console.log(str[Symbol.iterator]());
|
4.4 对象是没有内置的迭代器的,但是我们可以给它创建一个自己的迭代器
首先我们先看一看对象有没有内置的迭代器,代码如下所示:
1 2
| let obj = {}; console.log(obj[Symbol.iterator]);
|
此时你会发现打印出来的是undefined,再一次的证实了对象是没有内置的迭代器的,但是我们可以给它创建一个自己的迭代器,代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| let obj = { a: 1, b: "b", [Symbol.iterator]() { let index = 0; return { next: ()=>{ let keys = Object.keys(this); return index < keys.length ? {value: this[keys[index++]],done: false} : {value: undefined,done: true}; } } } }; let o = obj[Symbol.iterator](); console.log(o.next()); console.log(o.next()); console.log(o.next());
let obj = { a:1, b:"b", c:"d" }; obj[Symbol.iterator] = function(){ let index = 0; return { next: ()=>{ let keys = Object.keys(this); return index < keys.length ? {value: this[keys[index++]],done: false} : {value: undefined,done: true}; } } }; let o = obj[Symbol.iterator](); console.log(o.next()); console.log(o.next()); console.log(o.next()); console.log(o.next());
|
5. 迭代器使用场景
5.1 for of循环
for(let a of b){}
for of的应用场景更加的广泛了,只要b是一个迭代器,它就是可以用一个for of来进行一个循环。
for of是可以使用break的,它的底层是调用next()方法,语义化更强。for of会自动调用迭代器中的next()方法。如:
1 2 3 4 5 6 7 8 9 10
| let names = ["xiaoming","xiaohong","xiaoli"]; for(var name of names){ console.log(111); if(name === "xiaohong"){ break; } }
|
5.2 数组新增方法
a. keys() 索引
b. values() 值
c. entries() 把索引和值都打印出来
1 2
| let names = ["xiaoming","xiaohong","xiaoli"]; console.log(names.keys());
|
1 2
| let names = ["xiaoming","xiaohong","xiaoli"]; console.log(names.values());
|
1 2
| let names = ["xiaoming","xiaohong","xiaoli"]; console.log(names.entries());
|
5.3 解构赋值
1 2 3 4 5 6 7 8 9
| let names = ["xiaoming","xiaohong","xiaoli"]; for(let [index,name] of names.entries()){ console.log(name); }
|
5.4 …运算符(一般来说都是扩展运算符)
1 2 3
| let names1 = ["xiaoming","xiaohong","xiaoli"]; let names2 = ["xiaodai",...names1]; console.log(names2);
|