网站首页 > 基础教程 正文
什么是迭代器
迭代器是一种特殊的对象,它具有一些为迭代过程设计的接口。迭代器在结构上具有如下特征:
- 有一个next方法,每次调用都会返回一个结果对象
- 结果对象有两个属性:value和done。value表示下一个将要返回的值,而done是一个布尔状态,表达当前迭代是否已经结束。如果迭代还未完成,则done的值为false, 反之则为true
什么是可迭代对象
具有Symbol.iterator属性的对象,即为可迭代对象。在 ES6 中,所有集合对象,包括数组,字符串,Set集合,Map 集合。
既然说到了Symbol.iterator属性,那它是什么呢?其实它是一个特殊的函数。我们可以直接来使用这个属性来进行迭代:
let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();
console.log(iterator.next()) // {value: 1, done: false}
console.log(iterator.next()) // {value: 2, done: false}
console.log(iterator.next()) // {value: 3, done: false}
console.log(iterator.next()) // {value: undefined, done: true}
console.log(iterator.next()) // {value: undefined, done: true}
可以看到,Symbol.iterator其实就是一个函数,它的返回值是一个特殊的对象,这个对象有两个属性:value和done。当迭代完成时,done的值为true,而其值为undefined。迭代完成后可以继续调用,没有次数的限制,但其返回的结果对象为{value: undefined, done: true}。
如何模拟实现一个迭代器
首先Symbol.iterator是一个函数,它应该接收一个可迭代对象。因此我们可以创建一个函数:
function createIterator(items){}
其次该函数调用的结果会返回一个拥有next方法的函数:
function createIterator(items){
return {
next: function(){}
}
}
而调用该方法会返回一个包含了value和done属性的结果对象。且该结果对象的value是迭代的,而done是表示当前迭代是否完成。因此我们需要一个能够记录当前迭代位置的指针,并且每一次的调用都去移动该指针。
function createIterator(items){
let i = 0;
return {
next: function(){
return i < items.length ?
{value: items[i++], done: false} :
{value: undefined, done: true};
}
}
}
我们来测试一下该函数:
let iterator = createIterator([1,2,3]);
console.log(iterator.next()) // {value: 1, done: false}
console.log(iterator.next()) // {value: 2, done: false}
console.log(iterator.next()) // {value: 3, done: false}
console.log(iterator.next()) // {value: undefined, done: true}
console.log(iterator.next()) // {value: undefined, done: true}
判断对象是否为可迭代对象
既然可迭代对象是有Symbol.iterator属性的,那么我们便可以根据该属性来判断对象是否为可迭代对象:
function isIterable(object){
return typeof object[Symbol.iterator] === 'function'
}
内置迭代器
ES6 为集合对象提供了内置迭代器,在大多数情况下我们无须自己手动实现。
entries(), values(), keys()都会返回一个迭代器,但是它们的表现不同。但要注意虽然字符串也是可迭代对象,但是它没有这三个内置的迭代器方法,不过它可以使用for...of进行迭代。
- entries(),值为键值对的组合
- values(),值为集合的值
- keys(),值为集合的键名
我们可以使用for...of来访问迭代器。
entries迭代器
entries会返回一个数组,数组中包含两个元素,分别表示集合中每个元素的键和值。
由于集合对象的不同,返回值也有所不同。
let map = new Map();
map.set('address', 'BeiJing');
map.set('phone', '110');
for(let m of map.entries()){
console.log(m)
}
//['address', 'BeiJing']
//['phone', '110']
返回结果中第一个元素为键名,第二个元素为值。
let set = new Set(['a', 'b', 'c']);
for(let s of set.entries()){
console.log(s);
}
//['a', 'a']
//['b', 'b']
//['c', 'c']
Set 集合的返回结果中,第一个元素和第二个元素都是值,即将值作为了键。
let arr = ['a', 'b', 'c'];
for(let item of arr.entries()){
console.log(item)
}
//[0, 'a']
//[1, 'b']
//[2, 'c']
数组集合的返回结果中,第一个元素为数字索引,第二个值为集合的值。
let str = 'abc';
for(let s of str.entries()){
console.log(s);
}
// TypeError: str.entries is not a function or its return value is not iterable
即字符串是没有entries迭代器方法的。
而values与keys迭代器则分别是返回值和键。
不同集合类型的默认迭代器
如果我们直接使用for...of而不指定迭代器时,不同类型的集合会默认调用不同的迭代器。Map的默认迭代器是entries(),也很容易理解,因为对于Map来说,键和值是映射关系。而对于Set和数组集合来说,默认迭代器是values。
对于Map
let map = new Map();
map.set('address', 'BeiJing');
map.set('phone', '110');
for(let m of map){
console.log(m)
}
//['address', 'BeiJing']
//['phone', '110']
对于Set
let set = new Set(['a', 'b', 'c']);
for(let s of set){
console.log(s);
}
//a
//b
//c
对于数组
let arr = ['a', 'b', 'c'];
for(let item of arr){
console.log(item)
}
//a
//b
//c
迭代器的更多能力应该和生成器一起使用才能够体现出来,我们将在下一篇探讨迭代器与生成器的配合。
猜你喜欢
- 2024-10-23 js判断对象是否为空的方法归纳 js判断对象是否为空的方法归纳数据
- 2024-10-23 js中的迭代对象是什么 js迭代器iterator
- 2024-10-23 JavaScript遍历对象方法总结,原来有这么多,你掌握了几种?
- 2024-10-23 33个非常实用的JavaScript一行代码,建议收藏
- 2024-10-23 「翻译」JavaScript的可视化学习之六:生成器和遍历器
- 2024-10-23 JavaScript:Object对象的属性方法
- 2024-10-23 JavaScript:ES中的对象属性、Set、Map与对象拷贝
- 2024-10-23 腾讯最爱考的前端面试题:JavaScript 基础
- 2024-10-23 JavaScript ES6 - 使用 gulp 构建脚本编码
- 2024-10-23 判断JavaScript对象属性是否存在:全方位剖析与实践策略
- 最近发表
- 标签列表
-
- jsp (69)
- pythonlist (60)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- mysql教程 (60)
- pythonif (68)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- console.table (62)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)