# foreach区别对待Array和Set

{% embed url="https://v.douyin.com/r88dnH3/" %}

{% embed url="https://www.bilibili.com/video/BV1BS4y1p7DW/" %}

这一个小伙伴发来的一段Js代码

我们先不用读懂他在干什么

我们先运行一下，大家看 报错对吧

但是如果我把这改成一个数组

然后呢这就得用push了

然后我们再运行一下

大家看，没问题了

后来我发现啊

原因出在这个foreach上面

我们来看这个例子

这是一个简单的数组

我现在呀用foreach把它遍历一下

element

好我们再来执行一下这个

大家看：1、2、3没问题对吧

但是如果我在这每次循环的时候呢

都往array里面push一个新的元素

这个元素呢就是

加

也就是说：我们在array的循环里面

往array添加新的元素

我们来看一下

还是123没问题

但是如果我们在最终打印下结果

大家看101、102、103其实加上来了

但是啊如果我们把这个改成new set

然后呢这用add我们再来试一下

注意看

大家看，无限循环

所以我们就会发现对于数组来说

在 foreach 这个循环里面

新添加的元素没有参与循环

但是对于这个set来说

他就参与了循环

那具体

我们先来看一下

ECMA标准里面的这段解释

翻译过来的大概意思就是说

这个foreach循环的元素的范围

注意是范围

是在第一次调用callback之前设置的

也就说在foreach调用以后

我们再往元素里添加的

这个新元素的范围是不会被访问的

为什么强调范围呢

我们再来看一下这个

还是刚才这个例子我们还是用数组

我们这回不往里添加

100了我们先回到这个打印的效果

我们先来执行一下

打开123没问题对吧

但是啊

我们让这element它等于一的时候

我们往它后面插入一个元素

ARE

点 splice

我们让他在第二个元素的

插入一个100吧

好我们再来打印一下大家看

就变成了一、一百、二了

也就是说他还是循环三遍

但是呢

它里面元素的内容已经变成四个了

大家注意看

我在这最终再打印一下array

他就变成1、100、2、3了

但是呢他还是循环三遍

只是第二个元素变了

所以呢这里强调的是一个处理的范围

那虽然我们看不到foreach的原代码哈

但是我们可以推断出来

他大概是这样写的

比如我们写一个普通的for循环

i < array.length

然后 i++

然后现在在这打印

这是123没有问题是这样的

那基于这个for循环

我们再往里添加一下试试

array.push(element + 100)

我们再来试一下

大家看，无限循环了

跟刚才那个Set一样

他新插入的元素也参与了后续的循环

但是如果我们把这个缓存成一个数组 （口误：缓存成变量）

也就是说length

然后呢

让这小于length

我们再来试一下

大家看，跟刚才是不是一样效果

所以呢其实我们用数的foreach啊

就有点像这样来写

好那至于为什么

我们这块用Set 效果就不一样呢

这块我猜测

是因为它这个循环的机制不一样

因为它不是用下标来循环的

它是内部用的迭代器

所以呢他这块新加的元素呢

会参与到后续的循环里

边去

最后啊我们再回到这个小伙伴

发来的这段代码

为什么他用这个new Set就会报错呢

原因是他这个fn方法里面

不但往这个额瑞添加新元素了

而且由于他这个逻辑哈

他加入了空的元素

那空肯定是没办法调用的

但是对于array来说呢

你添加的元素

素根本就不会参与到循环里边

所以后加的那个空不会在这执行
