【js】js中的for-in(你让我情何以堪)

【js】js中的for-in(你让我情何以堪)

最近在写一个小demo,码前端的时候发现一个js中很深的坑:
 因为前端收到服务器端传来的数据是一串用“,”隔开的字符串,在处理的时候直接用string.spilt()方法给断成了一个字符串数组,以便食用;所以在取数组元素的时候想到了用for-in去遍历。

然鹅!
然鹅!
然鹅!

我还是太年轻了!完全不知道自己已经陷入了一个巨大(zhi zhang)的陷阱!本来完美无缺(bu shi hen lan)的代码突然变得焦躁起来,大家似乎都对我有不同的意见,争先恐后的抱起了八阿哥。呜呜呜,不说了,浪费半天时间……
上代码!

一开始我是这么搞的

var arr = ["please", "dont", "cast", "my", "type"];

for (var a in arr) {
    document.getElementById(a).value = a;
}

原代码比较繁琐,上面是示例代码,大概就是这么个操作。
然后就一直报错啊,提示信息如下:
Uncaught TypeError: Cannot set property ‘value’ of null at :2:38
  到这基本上就知道是因为dom元素没有被拿到了,就在循环体里面的第一行加了句console.log(document.getElementById(a)),打出来是null没错,但想来想去还是不明白为什么(压根就没怀疑for-in这奇葩的语句)。
  折腾了半天没办法,只好再前置了一句console.log(a)想着试一试。诶???为什么输出的是些奇怪的东西?

var arr = ["please", "dont", "cast", "my", "type"];

for (var a in arr) {
    console.log(a);
    //document.getElementById(a).value = a;
}
//
 0
 1
 2
 3
 4
 shuffle

这是把arr的索引给遍历出来了吗?再查看一下a的类型:

var arr = ["please", "dont", "cast", "my", "type"];

for (var a in arr) {
    console.log(typeof a);
    //document.getElementById(a).value = a;
}
6 string

这什么鬼?难道for-in是用来遍历对象的索引的?
验证一下吧:

//
> var ob = {1:"aa", 2:"bb", 3:"cc"}
< undefined
> ob
< {1: "aa", 2: "bb", 3: "cc"}
  1: "aa"2: "bb"3: "cc"__proto__: Object
> for (var o in ob) {
      console.log(o);
  }
> 1
> 2
> 3
> undefined

//
> var oc = {"a1": "aaa", "a2": "bbb", "a3": "ccc"}
< undefined
> oc
< {a1: "aaa", a2: "bbb", a3: "ccc"}
  a1: "aaa"a2: "bbb"a3: "ccc"__proto__: Object
> for (var o in oc) {
      console.log(o);
  }
> a1
> a2
> a3
< undefined

看来,对于“对象”,for-in语句遍历出来的是属性没错了。
!!!但是,对于数组,不要用for-in去遍历它的索引,因为会出现莫名其妙的东西,比如上面遍历数组的代码,最后一个遍历出的是shuffle,这个是数组原型链中的一个属性,在这里被莫名其妙的搞出来了。

在js中一般使用的循环有两种

1.常规的for(var i=0;i<length;i++)

2.for-in:for(var item in list)

但是个人更喜欢使用第一种循环,而不喜欢几乎从来不使用for-in这种写法,原因如下:

1.第一种写法能够很好的控制循环何时结束,以及对应的索引;而第二种循环无法控制

2.第二种写法在某种情况下,可能会导致一些奇怪的bug
在这里插入图片描述
以上是在jsBin中编辑的代码,在第一段代码中,对js的数组Array添加了一个新的方法(prototype 属性使您有能力向对象添加属性和方法),为了在某些时候能够方便使用。此时,如果用for-in循环出数组arr的内容,会发现在本来想要得到的0,1,2,3的后面会多一个function(){alert(“myfunction”);},这应该不是我们想要得到的结果。

注意:for…in循环会把某个类型的原型(prototype)中方法与属性给遍历出来,所以这可能会导致代码中出现意外的错误

上面只是简单的遍历一个数组,可能出现的问题还不够明显,如下所示
在这里插入图片描述

如果我们遍历的数组中存放的是业务对象,此时会发现,最后一次输出的是空,在被循环的数组中不存在这个名称为空的人员,此时出现的错误就导致某些业务无法正常使用或显示。
对于使用for-in可能导出的bug,有两种方式避免

1.在循环数组集合时,不使用for-in,统一使用for(var i=0;i<length;i++)这种形式;

2.在for-in循环中增加一个hasOwnProperty的判断;

hasOwnProperty函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性。如果有,返回true,否则返回false
该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法。
在这里插入图片描述

上述的两种方式,个人觉得第一种方式更好,因为是从根源上避免问题的发生,对于第二种方式,完全是为了解决问题而增加额外的处理完全没有这个必要。

发布了53 篇原创文章 · 获赞 141 · 访问量 2504

猜你喜欢

转载自blog.csdn.net/qq_45768871/article/details/105233983