1

困惑

在练习数组操作的时候,希望实现删除数组中特定元素(比如删除字符“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"]

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


夜行风
1k 声望50 粉丝

字节跳动持续招人中~