For循环与ForEach的三大区别(学习记录)

参考:CRMEB的推文JavaScript for 循环 | 菜鸟教程

目录

 本质区别

语法区别

对forEach的传参

对for循环的终止

for循环控制起点

性能比较

总结


 本质区别

         for循环是一种从js推出时就提出来的遍历行为;

        forEach则是在后来ES5中提出的迭代行为

遍历:指的对数据结构的每一个成员进行有规律的且为一次访问的行为。

迭代:迭代是递归的一种特殊形式,是迭代器提供的一种方法,默认情况下是按照一定顺序逐个访问数据结构成员。迭代也是一种遍历行为。

let arr = [1, 2, 3, 4]  // 可迭代对象
let iterator = arr[Symbol.iterator]()  // 调用 Symbol.iterator 后生成了迭代器对象
console.log(iterator.next()); // {value: 1, done: false}  访问迭代器对象的next方法
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

可以看出,只要是可迭代对象,调用内部的 Symbol.iterator 都会提供一个迭代器,并根据迭代器返回的next 方法来访问内部

语法区别

对forEach的传参

arr.forEach((self,index,arr) =>{},this)
  • self: 数组当前遍历的元素,默认从左往右依次获取数组元素。
  • index: 数组当前元素的索引,第一个元素索引为0,依次类推。
  • arr: 当前遍历的数组。
  • this: 回调函数中this指向。

 如果我们需要对一个数组去重,for循环体系长这样

let arr1 = [1, 2, 1, 3, 1];
let arr2 = [];
     for (let i = 0; i < arr1.length; i++) {
         if (arr2.indexOf(arr1[i]) == -1) {
             arr2.push(arr1[i]);
         }
     }
     console.log(arr2);

而forEach长这样

let arr1 = [1, 2, 1, 3, 1];
let arr2 = [];
    arr1.forEach(function (self, index, arr) {
        arr.indexOf(self) === index ? arr2.push(self) : null;
    });
    console.log(arr2);

可以看出,for循环是将整个数组多次遍历,而forEach只需要找到第一次出现的索引进行比对,在数据量大的时候能显著提升效率

对for循环的终止

        在js中有break return continue 对函数进行中断或跳出循环的操作,我们在 for循环中会用到一些中断行为,对于优化数组遍历查找是很好的,但forEach是迭代器,只能一次遍历至结束,不可以中途遍历或停止

let arr = [1, 2, 3, 4],
        i = 0,
        length = arr.length;
      for (; i < length; i++) {
        console.log(arr[i]); //1,2
        if (arr[i] === 2) {
          break;
        }
      }

      arr.forEach((self, index) => {
        console.log(self);
        if (self === 2) {
          break; //报错
        }
      });

      arr.forEach((self, index) => {
        console.log(self);
        if (self === 2) {
          continue; //报错
        }
      });

 包括return在内,都不会生效(但是return不会报错)

let arr = [1, 2, 3, 4];

      function find(array, num) {
        //声明一个find函数,接收两个参数,一个是数组,一个是要查找的值
        array.forEach((self, index) => {
          //遍历数组
          if (self === num) {
            //如果数组中的值等于要查找的值
            return index; //返回该值的索引
          }
        });
      }
      let index = find(arr, 2); 
      console.log(index);// undefined

for循环控制起点

就像上文说的,forEach不可控制终点起点,但for循环可以

let arr = [1, 2, 3, 4],
    i = 1,
    length = arr.length;

for (; i < length; i++) {
    console.log(arr[i]) // 2 3 4
};

而forEach中的index,不论是删除或是更改,都是无法生效的

let arr = [1, 2, 3, 4];
      arr.forEach((item, index) => {
        index++;
        console.log(item); // 1 2 3 4
      });

性能比较

性能比较:for > forEach > map

原因:

for:for循环没有额外的函数调用栈和上下文,所以它的实现最为简单。
forEach:对于forEach来说,它的函数签名中包含了参数和上下文,所以性能会低于 for 循环。
map:map 最慢的原因是因为 map 会返回一个新的数组,数组的创建和赋值会导致分配内存空间,因此会带来较大的性能开销。如果将map嵌套在一个循环中,便会带来更多不必要的内存消耗。

总结

  1. 语法:foreach是一种迭代数组或集合元素的简化语法,而for是一种传统的循环语法。
  2. 灵活性:foreach比for更灵活,可以在MoveNext()和GetCurrent()方法中编写自定义的代码。
  3. 循环规则:自定义的类如果实现了IEnumerable接口,就可以使用foreach循环,而不管内部是否有一个真实的数组,并且可以自定义循环的规则。
  4. 使用场景:从面向对象的原则来看,foreach循环更适于多数情况的使用。而对于某些特殊场景,如需要直接访问数组的索引或需要灵活控制循环条件,使用for循环更为合适。
  5. 错误检测:在使用foreach遍历一个数组时,如果数组元素的类型与foreach循环变量的类型不匹配,编译时就能检测出来并报错。而for循环在这方面没有这样的检查机制。
  6. 性能:for循环的性能通常比foreach循环要好,因为foreach循环在执行时需要进行额外的函数调用和上下文考虑。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦雨Chili

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值