ECMAScript6(14):iterator 迭代器

}

技巧1: 添加以下代码, 使 for…of 可以遍历 jquery 对象:

$.fn[Symbol.iterator] = [][Symbol.iterator];

技巧2: 利用 Generator 重新包装对象:

function* entries(obj){

for(let key of Object.keys(obj)){

yield [key, obj[key]];

}

}

var obj = {

red: “#ff0000”,

green: “#00ff00”,

blue: “#0000ff”

};

for(let [key, value] of entries(obj)){

console.log(${key}: ${value}); //依次输出 “red: #ff0000”, “green: #00ff00”, “blue: #0000ff”

}

几种遍历方法的比较

  • for 循环: 书写比较麻烦

  • forEach方法: 无法终止遍历

  • for…in: 仅遍历索引, 使用不便捷; 会遍历原型链上的属性, 不安全; 会遍历非数字索引的数组属性;

  • for…of:

iterator 与 [Symbol.iterator]

iterator 遍历过程是这样的:

1. 创建一个指针对象, 指向当前数据结构的起始位置。即遍历器的本质就是一个指针。

2. 调用一次指针的 next 方法, 指针指向第一数据成员。之后每次调用 next 方法都会将之后向后移动一个数据。

3. 知道遍历结束。

我们实现一个数组的遍历器试试:

var arr = [1, 3, 6, 5, 2];

var it = makeIterator(arr);

console.log(it.next()); //Object {value: 1, done: false}

console.log(it.next()); //Object {value: 3, done: false}

console.log(it.next()); //Object {value: 6, done: false}

console.log(it.next()); //Object {value: 5, done: false}

console.log(it.next()); //Object {value: 2, done: false}

console.log(it.next()); //Object {value: undefined, done: true}

function makeIterator(arr){

var nextIndex = 0;

return {

next: function(){

return nextIndex < arr.length ?

{value: arr[nextIndex++], done: false} :

{value: undefined, done: true}

}

};

}

由这个例子我们可以看出以下几点:

  • 迭代器具有 next() 方法, 用来获取下一元素

  • next() 方法具有返回值, 返回一个对象, 对象 value 属性代表下一个值, done 属性表示是否遍历是否结束

  • 如果一个数据结构本身不具备遍历器, 或者自带的遍历器不符合使用要求, 请按此例格式自定义一个遍历器。

其实一个 id 生成器就很类似一个遍历器:

function idGen(){

var id = 0;

return {

next: function(){ return id++; }

};

}

var id = idGen();

console.log(id.next()); //0

console.log(id.next()); //1

console.log(id.next()); //2

//…

对于大多数数据结构, 我们不需要再像这样写遍历器函数了。因为他们已经有遍历器函数[Symbol.iterator], 比如Array.prototype[Symbol.iterator] 是数组结构的默认遍历器。

下面定义一个不完整(仅包含add()方法)的链表结构的实例:

function Node(value){

this.value = value;

this.next = null;

}

function LinkedList(LLName){

this.head = new Node(LLName);

this.tail = this.head;

}

var proto = {

add: function(value){

var newNode = new Node(value);

this.tail = this.tail.next = newNode;

return this;

}

}

LinkedList.prototype = proto;

LinkedList.prototype.constructor = LinkedList;

LinkedList.prototype[Symbol.iterator] = function(){

var cur = this.head;

var curValue;

return {

next: function(){

if(cur !== null){

curValue = cur.value;

cur = cur.next;

return {value: curValue, done: false}

} else {

return {value: undefined, done: true}

}

}

};

}

var ll = new LinkedList(“prime”);

ll.add(1).add(2).add(3).add(5).add(7).add(11);

for(let val of ll){

console.log(val); //依次输出 1, 2, 3, 5, 7, 11

}

注意, 如果遍历器函数[Symbol.iterator]返回的不是如上例所示结构的对象, 会报错。

当然, 如果不不喜欢用for…of(应该鲜有这样的人吧), 可以用 while 遍历:

var arr = [1, 2, 3, 5, 7];

var it = arr[Symbol.iterator];

var cur = it.next();

while(!cur.done){

console.log(cur.value);

cur = it.next();

}

以下操作会在内部调用相应的 iterator:

  • 数组的解构赋值

  • 展开运算符

  • yield* 后面带有一个可遍历结构

  • for…of

  • Array.from() 将类数组对象转换为数组

  • Map(), Set(), WeakMap(), WeakSet() 等构造函数传输初始参数时

  • Promise.all()

  • Promise.race()

Generator 与遍历器

iterator 使用 Generator 实现会更简单:

var it = {};

it[Symbol.iterator] = function* (){

var a = 1, b = 1;

var n = 10;

while(n){

yield a;

[a, b] = [b, a + b];

n–;

}

}

console.log([…it]); //1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

当然, 以上代码还可以这样写:

var it = {

*Symbol.iterator{

var a = 1, b = 1;

var n = 10;

while(n){

yield a;

[a, b] = [b, a + b];

n–;

}

}

}

console.log([…it]); //[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

遍历器对象的其他方法

以上的遍历器对象只提到了 next() 方法, 其实遍历器还有 throw() 方法和 return() 方法:

  • 如果遍历终止(break, continue, return或者出错), 会调用 return() 方法

  • Generator 返回的遍历器对象具throw() 方法, 一般的遍历器用不到这个方法。具体在 Generator 中解释。

function readlineSync(file){

return {

next(){

if(file.isAtEndOfFile()){

file.close();

return {done: true};

}

},

return(){

file.close();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

本涵盖了95%以上前端开发知识点,真正体系化!**

[外链图片转存中…(img-r4qHjamg-1713482675127)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

[外链图片转存中…(img-JbLW7fx0-1713482675127)]

最后

[外链图片转存中…(img-4B88Mzne-1713482675127)]

[外链图片转存中…(img-eRHiixs9-1713482675127)]

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值