java 可迭代对象,什么是可迭代对象(Iterable objects)?

能够将可迭代对象理解为“宽泛意义上的数组”——就是说,不必定是数组(Array.isArray(iterable) 返回 false),但却可以被 for...of 循环遍历。java

概览

可迭代对象不必定是数组,数组必定是可迭代对象。

每一个可迭代对象必然包含一个 [Symbol.iterator]  方法属性

字符串也是可迭代对象

26a6b19a39fcf80f25347f35daf150e0.png

改造普通对象

咱们举一个例子,下面有一个对象:数组

let range = {

from: 1,

to: 5

};

// 咱们想用 for..of 遍历 range,获得从 1(from) 到 5(to) 的天然数

// for(let num of range) { consol.log(num) } // 遍历结果 1 -> 2 -> 3 -> 4 -> 5

复制代码

明眼人一看,就知道 range 不就是个普通对象嘛,跟可迭代对象有什么关系呢?还要用 for..of 遍历,遍历结果还要是 1 -> 2 -> 3 -> 4 -> 5,这不扯淡呢吗?说的对,如今确定是扯淡,那是由于咱们啥都没作呢,可不是扯淡吗?函数

为了能让 range 这个普通对象变为可迭代对象,咱们须要先来了解下 Symbol.iterator 这个系统预置变量。ui

Symbol.iterator

咱们先来看下,这个属性的描述是怎样的。this

Object.getOwnPropertyDescriptor(Symbol, 'iterator')

// {

// value: Symbol(Symbol.iterator),

// writable: false,

// enumerable: false,

// configurable: false

// }

复制代码

由结果可知,这个属性咱们是修改不了的。spa

下面咱们为上面的 range 对象添加一个 [Symbol.iterator]  方法属性——对的,这个属性的属性值是函数,每一个可迭代对象都有一个 [Symbol.iterator]  方法属性,没有的话,确定不是可迭代对象。code

let range = {

from: 1,

to: 5

}

// 1. for..of 循环首先会调用对象上的 [Symbol.iterator] 属性——range[Symbol.iterator](),

// 属性 range[Symbol.iterator] 称为“迭代对象生成器”或“迭代对象生成函数”

range[Symbol.iterator] = function(){

// range[Symbol.iterator]() 的调用结果,会返回一个包含 next 方法的对象,

// 这个对象称为“迭代对象”

// 2. 接下来, for..of 就是彻底在跟这个迭代对象打交道了

return {

current: this.from,

last: this.to,

// 3. 每次 for..of 循环一次,就要调用一次 next 方法

next() {

// 4. 从 next 方法返回的对象中,咱们能得到当前遍历的值(value)以及遍历是否结束的标记(done)

if (this.current <= this.last) {

return { done: false, value: this.current++ }

} else {

return { done: true }

}

}

}

}

复制代码

for...of 循环遍历的本质是:cdn

for..of 循环首先会调用对象上的方法属性 [Symbol.iterator]——range[Symbol.iterator](),获得一个包含 next 方法的对象。

这个包含 next 方法的对象称为迭代对象(iterator object)

属性 range[Symbol.iterator] 被称为迭代对象生成器或迭代对象生成函数

接下来, for..of 就是彻底在跟这个迭代对象打交道了,

每次 for..of 循环一次,就要调用一次 next 方法,

从 next 方法返回的对象中({ done: ..., value: ... }),咱们能得到当前遍历的值(value)以及遍历是否结束的标记(done)。

通过上面的叙述,咱们还能够将可迭代对象定义为:可以生成“迭代对象”的对象。

** 对象

遍历改造对象

如今对改造后的 range 对象进行遍历。

let range = {

from: 1,

to: 5

}

range[Symbol.iterator] = function(){...}

for (let num of range) {

console.log(num) // 1, 而后是 2, 3, 4, 5

}

复制代码

很酷啊,如今能够一次遍历出 1 -> 2 -> 3 -> 4 -> 5 这 5 个数字了。

手动遍历可迭代对象

由于好玩,我们模仿 for...of 循环内部执行流程,纯手工写一下遍历可迭代对象的逻辑吧。

这里会用到 while 循环:

// 下面的写法,等同于

// for (let num of range) { console.log(num) };

let iterator = range[Symbol.iterator]();

while (true) {

let result = iterator.next();

// 标记结束(done 为 true),就终止循环,结束遍历

if (result.done) break;

// 不然,打印当前遍历的值

console.log(result.value);

}

复制代码

首先,手动调用 range[Symbol.iterator] 方法,得迭代对象

在 while 循环内部:

若是标记结束(done 为 true),就终止循环,结束遍历

不然,打印当前遍历的值

内置可迭代对象

前面咱们说过:可迭代对象不必定是数组,如今再加一句:数组必定是可迭代对象。根据经验,咱们知道数组是能够用 for...of 循环遍历的。

数组

881e0ef656242eeb52db8d47b682cb58.png

遍历 symbols 被 for...of 循环成功遍历了。这是意料之中的事情,但咱们再来看下,这个数组对象里是否是有个叫 Symbol.iterator 的属性 🕵️‍♂️

b09b6906d950a129b37c48f9eeff1ca8.png

果真!

字符串

字符串也是可迭代对象。证据以下:

16aa4fa601da8a38f8965d13aca06a18.png

再来找找 Symbol.iterator 属性。

f56a267cdff5d82357514e1fb4ea0aaa.png

Map 和 Set

Map 和 Set 也是可以被 for...of 遍历的。在这里就很少举例了,直接展现它们各自部署的  Symbol.iterator 属性。

8564b30540f3c4806ce1d9a5adeb5258.png

0ba1e4b8cb8e467a903f0951073d518f.png

从上面的截图里,咱们能够总结出一点内容来:

Map 对象默认的迭代对象生成器函数是 map.entries(),而

Set 对象默认的迭代对象生成器函数是 map.values()

更多关于 Map 和 Set 对象的遍历内容,请参考《遍历 Map 和 Set》。

(完)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值