首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS中不同的循环方式和注意事项总结

JS中不同的循环方式和注意事项总结

作者头像
何处锦绣不灰堆
发布2022-08-07 12:57:04
1K0
发布2022-08-07 12:57:04
举报
文章被收录于专栏:农历七月廿一农历七月廿一

文章目录

写在前面

这篇文章主要是将js中循环的方式进行一个总结,包括常见的循环方式以及需要注意的事项,我尽可能的写的明白一些,因为很多太小的细节可能我自己也不会完全深入的搞明白!

循环常见的方式
  • for
  • while
  • for in
  • for of
  • forEach
基础数据准备
		//声明一个密集数组,如果不进行fill填充的话,默认的是一个稀疏型数组
        let arr = new Array(9999999).fill(9) //用于测试性能
        let tR = [2, 3, 4, 5, 3, 2, 1] //用于测试特性
        let i = 0 //for 循环使用
        let obj = {
            name: 'jim',
            [Symbol('sm')]: 800,
            get: function () { },
            childObj: {},
            num: 900,
            1: 888,
        } //for of 和for in测试特性使用
性能比较
        //测试普通的for循环
        console.time('for')
        for (let i = 0; i < arr.length; i++) { }
        console.timeEnd('for')
        //for: 6.968017578125 ms

        //测试while循环
        console.time('while')
        while (i < arr.length) {
            i++
        }
        console.timeEnd('while')
        //while: 34.88720703125 ms

        //测试for in
        console.time('for in')
        for (let i in arr) { }
        console.timeEnd('for in')
        //for in: 2076.422119140625 ms

        //测试for of
        console.time('for of')
        for (let i of arr) { }
        console.timeEnd('for of')
        //for of: 129.52490234375 ms

        //测试foreach
        console.time('for each')
        arr.forEach(() => { })
        console.timeEnd('for each')
        //for each: 88.530029296875 ms
特性
for循环
      	/**
	           == for 循环
	           + 可定制化比较强 可以随时break 和 continue 来决定要不要继续循环
	           + 判断条件可以随意修改
	           + 可以在循环的过程中进行每一项值的修改 也可以改变源数组的数据
	           - 取值比较麻烦,需要使用数组[下标]的方式进行值的操作
        */
        new Promise(res => {
            for (; i < tR.length; i++) {
                if (i % 2 == 0) {
                    tR[i] = 'new'
                }
            }
            res()
        }).then(() => {
            console.log(tR) //['new', 3, 'new', 5, 'new', 2, 'new']
        })
while循环
	    /**
	         == while 循环
	         + 循环可以通过判断条件进行终止
	         + 判断条件可以随意修改
	         + 可以在循环的过程中值不被修改,源数组不会被更改
	         - 一般适用于不知道循环次数的前提下,使用某一个条件进行终止循环 效率和for差不多,只是不知道循环次数的时候可以使用while
	    */
        new Promise(res => {
            while (i > tR.length) {
                i++
                // delete(tR[i])
                if (i % 2 == 0) {
                    tR[i] = 'new'
                }
            }
            res()
        }).then(() => {
            console.log(tR) //[2, 3, 4, 5, 3, 2, 1]
        })   
forEach
	    /**
	          == forEach 循环
	          + 语法简单
	          - 遍历的时候无法修改和删除集合数据
	          - 方法不能使用break,continue语句跳出循环,或者使用return从函数体返回,对于空数组不会执行回调函数
	    */
        new Promise(res => {
            tR.forEach((v, i, a) => {
                //i不会被改变
                i = i + Number(v)
                if (i % 2 == 0) {
                    return
                }
                if (v == 2) {
                    //可以在判断条件里面执行业务逻辑,但是数据没办法传递出去
                    console.log(v) // 2
                    console.log(a) //[2, 3, 4, 5, 3, 2, 1]
                }
                //不会被终止,源数组不会被改变
            })
            res()
        }).then(() => {
            console.log(i) //0
        })
       // 源数组不会被改变
       new Promise(res => {
            tR.forEach((v, i, a) => {
                delete (v % 2 == 0)
            })
            res()
        }).then((a) => {
            console.log(tR) //[2, 3, 4, 5, 3, 2, 1]
        })
for in
		/**
          == for in 循环
          + 语法简单
          + 可以用来遍历对象
          - 遍历的时候无法修改和删除集合数据
          - 方法不能使用break,continue语句跳出循环,或者使用return从函数体返回,对于空数组不会执行回调函数
        */
	     //可以改变源数组 删除数组
        let pro = new Promise((res => {
            for (let v in tR) {
                delete (tR[v])
            }
            res()
        }))
        p.then(r => {
            console.log(tR) //稀疏数组 [length = 7]
        })
        //遍历数组
        new Promise(res => {
            for (let v in tR) {
                i = i + tR[v]
            }
            res()
        }).then(() => {
            console.log(i) //20
        })
        
        //遍历对象需要注意的点
        Object.prototype.fn = function fn() { } //公有属性 函数
        Object.prototype.O = 'obj' //公有属性string
        // 数字->string->function->对象->number 但是遍历不到Symbol 属性  同时会将公有属性遍历出来
        for (let k in obj) {
            console.log(obj[k])
            /**
             ceshi.html:158 888
             ceshi.html:158 jim
             ceshi.html:158 ƒ () { }
             ceshi.html:158 {}
             ceshi.html:158 900
             ceshi.html:158 ƒ fn() { }
             ceshi.html:158 obj
             */
        }
        for (let k in obj) {
            //将非私有属性 过滤掉
            if (obj.hasOwnProperty(k)) {
                console.table(obj[k])
            }
            /**
             ceshi.html:169 888
             ceshi.html:169 jim
             ceshi.html:169 function () { }
             ceshi.html:169 
             ceshi.html:169 900 
             */
        }
        //获取symbol属性
        console.log(Object.getOwnPropertySymbols(obj)) //[Symbol(sm)]
for of
		 /**
          == for of 循环
          + 语法简单
          - 遍历的时候无法修改和删除集合数据
          - 方法不能使用break,continue语句跳出循环,或者使用return从函数体返回,对于空数组不会执行回调函数
          原理是 查看属性中有没有symbol.iterator迭代器 也就是说我们可以通过改变Symbol的规则 进行更改遍历的结果输出 代码如下
        */
		//删除数组 不改变源数组
        new Promise(res => {
            for (let v of tR) {
                delete (v % 2 == 0)
            }
            res()
        }).then(() => {
            console.log(tR) //[2, 3, 4, 5, 3, 2, 1]
        })

        //遍历数组
        new Promise(res => {
            for (let v of tR) {
                i = i + v
            }
            res()
        }).then(() => {
            console.log(i) //20
        })

        //使用for of 遍历类数组 给对象添加iterator的属性
        let O = {
            0: 1,
            1: 2,
            2: 3,
            length: 3 //不添加lenth属性的话,不算一个类数组
        }
        O[Symbol.iterator] = Array.prototype[Symbol.iterator]
        for (let v of O) {
            console.log(v) //1、2、3
        }

  		 // 重写iterator方式 既然for of 是根据iterator规则来的,那么我们就可以重写他的规则进行满足我们的业务需求
        tR[Symbol.iterator] = () => {
            let i = 0
            return {
                //每一个iterator都必须有一个next函数,他执行次数多少是根据done来判断的,true的时候就不执行了,否则一直执行
                next() {
                    // i++
                    //这里我们改变他的遍历次数
                    i += 2
                    if (i > tR.length - 1) {
                        return {
                            done: true,
                            value: null
                        }
                    } else {
                        return {
                            done: false,
                            value: tR[i]
                        }
                    }
                }
            }
        }
        for (let k of tR) {
            console.log(k) // 4、3、1
        }

总结

这篇文章不是水的,其实是我最近想将js中的一些基础知识也总结一下,这样晚上一下我的知识体系,也重温一下之前漏掉的一些细节,这样做的一个目的是巩固自己的基础,不至于在一些很简单的问题上浪费时间,比如我们写代码的时候,使用for in 进行对象的遍历,突然发现莫名其妙多了属性,那么这个时候你就要检查一下是不是别的同事写了一些Object的公共属性进去,自己也没有进行过滤导致的,诸如此类,所以可能这些总结每一个点都不难,但是系统起来就并非易事,还是脚踏实地的慢慢琢磨!拜了个白

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 写在前面
    • 循环常见的方式
      • 基础数据准备
        • 性能比较
          • 特性
            • for循环
            • while循环
            • forEach
            • for in
            • for of
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档