资讯专栏INFORMATION COLUMN

for循环和for in在遍历数组中的区别

wangbinke / 673人阅读

摘要:举个例子,如果你的数组中有一个可枚举属性,循环将额外执行一次,遍历到名为的索引。就连数组原型链上的属性都能被访问到。某些情况下,可能按照随机顺序遍历数组元素。

困惑

在练习数组操作的时候,希望实现删除数组中特定元素(比如删除字符“1”)的功能
很容易地就想到了利用for循环和splice方法

for (let i = 0; i < hobbies.length; i++) {
        if (hobbies[i] == "1") {
            hobbies.splice(i, 1);
            i--;
        }
    }

测试结果
"1", "2", "3","1", "1", "4", "1"
"2", "3", "4"

如愿达成目标,不过想起来还有for in这个东西,似乎写起来更简洁
那用for in行不行呢

for(var i in hobbies)
    {
        if(hobbies[i]=="1")
        {
            hobbies.splice(i,1);
            i--;
        }
    }
    
测试结果
"1", "2", "3", "1", "1","4"
"2", "3", "1", "4"

为什么中间多了一个"1"出来?发生了什么?

测试

添加console.log语句观测i值的变化

for(var i in hobbies)
    {
        console.log("判断前"+i);
        if(hobbies[i]=="1")
        {
            hobbies.splice(i,1);
            i=i+1;
        }
        console.log("判断后"+i)
    }
结果
判断前0
判断后-1
判断前1
判断后1
判断前2
判断后1
判断前3
判断后3

可以看到,在第一次删去1后,i--由0变成了-1
但下一次判断的时候,i直接由-1跳到了1

隐藏的陷阱

在查询资料之后,才发现问题出在了i的类型上

标准的for循环中的i是number类型,表示的是数组的下标
但是for in循环中的i, 表示的是数组的key是string类型!

由于隐式类型转换的机制,这个区别被隐藏了起来
因为我测试的时候,用的是i--
而字符串,在运用递增递减符号的时候,会把它转换成number类型
因此虽然i是字符”1“,但也变成了0
如果我用的是i=i+1
字符串加数字,会把数字转化成字符串拼接,出现01这样的结果
那么这个区别就会被我监测到
另外,在splice函数中,参数用了字符串也并没有影响最后的结果,因为也进行了隐式转换

实际发生的事

在先前,我们删除了元素后,给i--,想当然地觉得下一次变量的值会+1,变回i,就可以对删除的元素后面的一个元素进行判断(因为它的角标数值由i+1,变成了i)
在for循环中是没事的,但在for in里面
i--这个操作其实没有任何意义,即便给i随便赋一个值,它的下一次取值依然是i+1
因为它是根据数组的元素键值(索引)来进行遍历的,string类型的0,1,2,3,4...arr.length-1已经排好了,并不会因为中途i的值有所变化而改变

除此之外,for in还有一些坑

•作用于数组的for-in循环体除了遍历数组元素外,还会遍历自定义属性。举个例子,如果你的数组中有一个可枚举属性myArray.name,循环将额外执行一次,遍历到名为“name”的索引。就连数组原型链上的属性都能被访问到。
•某些情况下,for in可能按照随机顺序遍历数组元素。

因此不适合用for in来遍历数组
for in适合用来遍历对象

P.S

如果用forEach呢
结果如下

hobbies.forEach(function(value,index,hobbies){
        console.log("判断前"+index);
        if(value=="1")
        {
            hobbies.splice(index,1);
            console.log(typeof index);
            index=index-1;
            // console.log("二"+i);
        }
        console.log("判断后"+index);
    });
["1", "2", "3", "1", "1", "4", "1"]
判断前0
number
判断后-1
判断前1
判断后1
判断前2
number
判断后1
判断前3
判断后3
判断前4
number
判断后3
["2", "3", "1", "4"]

数组中有几项,那么传递进去的匿名回调函数就执行几次

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103127.html

相关文章

  • JS 数组循环遍历方法的对比

    摘要:循环方法方法不改变原数组方法会给原数组中的每个元素都按顺序调用一次函数。筛选出过滤出数组中符合条件的项组成新数组代码方法方法为数组中的每个元素执行一次函数,直到它找到一个使返回表示可转换为布尔值的值的元素。 showImg(https://segmentfault.com/img/bV2QTD?w=1600&h=500); 前言 JavaScript 发展至今已经发展出多种数组的循环遍...

    BlackFlagBin 评论0 收藏0
  • 【快速入门系列】简述 for...in for...of 区别

    摘要:像和使用内置构造函数所创建的对象都会继承自和的不可枚举属性,例如的方法或的方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性更接近原型链中对象的属性覆盖原型属性。遍历数组时推荐使用,其中为数组每一项的值。 引言 在对数组或对象进行遍历时,我们经常会使用到两种方法:for...in 和 for...of,那么这两种方法之间的区别是什么呢?让我们来研究研究。 一...

    ashe 评论0 收藏0
  • 数组常见的遍历循环方法、数组循环遍历的效率对比

    摘要:场景检查数组中是否含有某个东西和是对立的案例案例是否包含为对象循环遍历效率对比参考参考原生实现等方法其他参考 1 遍历数组的方法 1-1、for / while 最普通的循环 效率最高 兼容ie6tips:for循环更适用于循环的开始和结束已知,循环次数固定的场合;while循环更适合于条件不确定的场合 1-2、for in 兼容ie6,效率最差(效率可看最下面的对比) for in...

    xfee 评论0 收藏0
  • 关于JS循环遍历

    摘要:关于循环遍历写下这篇文章的目的,主要是想总结一下关于对于集合对象遍历的方式方法,以及在实际应用场景中怎样去使用它们。的作用主要是去遍历对象的可枚举属性。例如索引,数值打印结果为当第二项不满足条件式跳出循环,返回。 关于JS循环遍历 写下这篇文章的目的,主要是想总结一下关于JS对于集合对象遍历的方式方法,以及在实际应用场景中怎样去使用它们。本文会主要介绍:while,for,forEac...

    eternalshallow 评论0 收藏0
  • JS中轻松遍历对象属性的几种方式

    摘要:当普通对象要转换成时就很有用,因为返回的格式与构造函数接受的格式完全相同。使用常规的构造函数可以将一个二维键值对数组转换成一个对象。在和早期标准中,根本没有指定属性的顺序。此函数还可以轻松地将纯对象属性映射到对象中。 为了保证的可读性,本文采用意译而非直译。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 自身可枚举属性 Object.keys() 方法会返回一个...

    isLishude 评论0 收藏0

发表评论

0条评论

wangbinke

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<