zoukankan      html  css  js  c++  java
  • js ,几张遍历,循环的方法

     忙了好一段时间,项目上线后终于有那么一点点空档期静下来整理一些问题了。当我们在开发项目的时候,用到遍历的地方肯定少不了,那么我们有那么多的遍历方法,在不同情况下用那种方法会更优雅而且还没bug呢?

      首先,我在这里先列出几种常见的遍历机制,然后针对部分来做一个我对它的理解,有不同看法的老铁也可以分享一下,下面是我列出来的几种遍历的方法,另外我们常用来中断循环的语句我在这里简单的提一下:

      a、continue: 中断本次循环;

      b、return和break直接跳出循环。

    复制代码
    // for
    var arr = [1, 2, 3]
    for(var i = 0; i < arr.length; i++) {
        //do something
    };
    
    // for...of...
    for(var i of arr) {
        //do something
    };
    
    // for...in..
    for(var i in arr) {
        //do something
    };
    
    // forEach()
    arr.forEach((item, index, arr) => {
        //do something});
    });
    // map() arr.map((value,index,array) => {   //do something });
    复制代码

      在开发上一个项目的时候,我在用for...in...这个方法遍历的时候就遇到一个诡异的bug,在android手机是完美的展示,但是在iPhone手机的时候,就出现了遍历后的数据竟然是翻倍的,而且数据是重复的。然后我就想着用array.forEach的方法,来解决问题总该行来吧,在正常逻辑的情况下是可以解决问题的,但是,在稍微复杂的逻辑了,有时候我们要中断forEach遍历时,这时候就会显得软弱无力了,因为在forEach的遍历机制里是不支持中断遍历的,然后我只能寻求其他的解决方案了。

      下面我在这对上述列举的遍历方法逐个逐个的分析一下,有些分析不到位的,或者有不同的看法的老铁们请分享你的看法:

      1. 普通的for循环

    var arr = [1, 2, 3]
    for(var i = 0; i < arr.length; i++) { // 这里的i是代表数组的下标
        console.log(i); // 0, 1, 2
    };

      最简单的一种,正常用的话也不会出现什么问题,想中断也可以中断,性能上也还可以。

      

      2. 优化版的for循环

    var arr = [1, 2, 3]
    for(var i = 0, len = arr.length; i < len; i++) { // 这里的i是代表数组的下标
    console.log(i); // 0, 1, 2 }; 

      使用临时变量,将长度缓存起来,避免重复获取数组长度,当数组较大时优化效果才会比较明显。这种方法基本上是所有循环遍历方法中性能最高的一种,并且这一类型的for循环可以通过用break来中断循环,如下图所示:

       

      3. for...of...遍历(这种遍历支持ES6)

    var arr = [1, 2, 3]
    for(var item of arr) { // item代表数组里面的元素
        console.log(item); // 1, 2, 3
    }; 

      1、 这是最简洁、最直接的遍历数组元素的语法

      2、 这个方法避开了for-in循环的所有缺陷

      3、 与forEach()不同的是,它可以正确响应break、continue和return语句

      4、性能要好于forin,但仍然比不上普通for循环

      4. forEach()

    var arr = [1, 2, 3];
    arr.forEach((item, index, arr) => { // item为arr的元素,index为下标,arr原数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]
    });

      这种遍历便捷还是挺便捷的,看起来优雅,对目标数组的操作很人性化,要元素给元素,要下标给下标,但是当某种情况你想中断遍历的时候,你就会感觉它就像鸡肋,食之无味,弃之可惜。由于foreach是Array型自带的,对于一些非这种类型的,无法直接使用(如NodeList),所以才有了这个变种,使用这个变种可以让类似的数组拥有foreach功能。而且forEach的性能也会比普通的for循环弱。又下面的例子我们可以看到,我们常用的return false是可以终止代码继续往下执行的,但是在forEach遍历中,并没有终止循环,所以在用forEach的时候,要考虑使用场景了。

      

      5.some()

    var arr = [1, 2, 3];
    arr.some((item, index, arr) => { // item为数组中的元素,index为下标,arr为目标数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]  
    })

      some作为一个用来检测数组是否满足一些条件的函数存在,同样是可以用作遍历的函数签名同forEach,有区别的是当任一callback返回值匹配为true则会直接返回true,如果所有的callback匹配均为false,则返回false。

      some() 方法会依次执行数组的每个元素:

    • 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
    • 如果没有满足条件的元素,则返回false。

      7. every()

    var arr = [1, 2, 3];
    arr.every((item, index, arr) => { // item为数组中的元素,index为下标,arr为目标数组
        return item > 0; // true
        return index == 0; // false
    })

      every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。

      every() 方法使用指定函数检测数组中的所有元素:

    • 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
    • 如果所有元素都满足条件,则返回 true。

       8. for...in...遍历

    var arr = [1, 2, 3]
    for(var item in arr) { // item遍历数组时为数组的下标,遍历对象时为对象的key值
        console.log(item); // 0, 1, 2
    };

      for...in更多是用来遍历对象,很少用来遍历数组, 不过 item 对应与数组的 key值,建议不要用该方法来遍历数组,因为它的效率是最低的。

      9. filter()

    var arr = [1, 2, 3];
    arr.filter(item => { // item为数组当前的元素
        return item > 1; // [2, 3]
    })

      filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

     

      

      10. map() 

    var arr = [1, 2, 3];
    arr.map(item => { // item为数组的元素
        console.log(item); // 1, 2, 3
        return item * 2; // 返回一个处理过的新数组[2, 4, 6]
    })

      map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

      map() 方法按照原始数组元素顺序依次处理元素。

      这种方式也是用的比较广泛的,虽然用起来比较优雅,但实际效率还比不上foreach

     

      上述简单的介绍了各种遍历的方法。

      在前面我有提到一个苹果手机遍历出现数据重复的bug,那么我在这里做一个用for...in...案例,首先来看看代码:

    复制代码
    for (let item in this.currentForm) {
      var subFormDataObj = {};
       if (this.currentForm[item].isRequired === 2 && !this.currentForm[item].subjectValue && this.currentForm[item].subjectType != 5) {
           this.isSubmit = true;
           this.hideLoading();
           this.Toast('尚有数据未完成,提交失败!');
           return false;
       } else {
           if (this.expressionTest(this.currentForm[item].subjectValue)) {
               this.Toast('内容不能含有表情符,请重新输入!');
               this.isSubmit = true;
               this.hideLoading();
               return false;
           }
           if (this.currentForm[item].subjectName.indexOf('手机号') > -1) {
               if(!this.checkPhone(this.currentForm[item].subjectValue)) {
                   this.isSubmit = true;
                   this.hideLoading();
                   return false;
               };
           }
           subFormDataObj.subjectId = this.currentForm[item].subjectId;
           subFormDataObj.subjectValue = this.currentForm[item].subjectValue;
           subFormDataObj.picture = this.currentForm[item].picurl;
           subFormDataObj.isRequired = this.currentForm[item].isRequired;
           if (this.currentForm[item].subjectType == 5) {
               if (this.listPicStr == '') {
                   this.isSubmit = true;
                   this.hideLoading();
                   this.Toast('尚有数据未完成,提交失败!');
                   return false;
               } else {
                  // subFormDataObj.picture = "data:image/jpeg;base64," + this.listPicStr.replace(/data:image/jpeg;base64,/g,'') || '';
               }
           }
           subFormData.push(subFormDataObj);
       }
    };
    alert(JSON.stringify(subFormData));
    复制代码

        

      我们看一下安卓手机和苹果手机alert出来的数据有什么区别:在截图中我们就可以发现,苹果手机整体遍历了2轮,这样个结果是不是很诡异?是的我也觉得很诡异,怎么来解决呢,很多很学会想到一些方法,比如用数组去重的方法,并且es6的去重方法很优雅(var newArr = Array.from(new Set(subFormData))),或者其他去重的方法,这样做并没有什么不好,比较方法有千千万,喜欢就好。当时因为考虑到里面的逻辑问题,我就直接改了一行代码,用了最普通的方法,因为性能上会有优势,所以我就用了普通的for循环解决了这个问题。

      换了一种遍历方法后,这个问题就解决了,在这里简单的做了一些开发时遇到的坑做了一些总结,有不同看法的各路大神,跪求分享!!!

    1、路在何方? 路在脚下 2、何去何从? 每个人都在探索,未来的方向在何处。如果说某些方向是世人已经公认的,那么就先按照公认的去走吧(ps:站在巨人的肩膀上看世界会清晰)。 如果说方向,当今世人还不清晰准确。那么就大胆往前走吧,对与错并不重要。心中的方向更加重要。
  • 相关阅读:
    SCI写作经典替换词,瞬间高大上!(转)
    最佳化常用测试函数 Optimization Test functions
    算法复杂度速查表
    VS 代码行统计
    CPLEX IDE 菜单栏语言设置( 中文 英文 韩文 等多国语言 设置)
    如何从PDF文件中提取矢量图
    Matlab无法打开M文件的错误( Undefined function or method 'uiopen' for input arguments of type 'char)
    visual studio 资源视图 空白 解决方案
    MFC DialogBar 按钮灰色不响应
    嗨翻C语言笔记(二)
  • 原文地址:https://www.cnblogs.com/yuanjili666/p/12096514.html
Copyright © 2011-2022 走看看