在练习数组操做的时候,但愿实现删除数组中特定元素(好比删除字符“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值的变化code
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适合用来遍历对象
若是用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"]
数组中有几项,那么传递进去的匿名回调函数就执行几回