不要用for in语句对数组进行遍历
for...in主要用于对数组和对象的属性进行遍历。for ... in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。
语法:for (variable in object) {...}
variable:
每次迭代,一个不同的属性名将会赋予variable。object:
可枚举属性被迭代的对象。
对数组操作
var a=[5,4,3,2,1]; var x=0; console.log(typeof x);//number for (x in a) { console.log("a["+x+"]: "+a[x]); console.log(typeof x);//string } console.log(x);//4 console.log(typeof x);//string //output: // a[0]: 5 // a[1]: 4 // a[2]: 3 // a[3]: 2 // a[4]: 1
可以发现在for in函数中变量以字符串的形式出现,这时候在函数中操作a[x+1]的话是无效的,x+1会进行字符串拼接。
对象操作
var obj={"1":"first", "two":"zoo", "3":"2", "three":"34", "4":"1", "2":"second" }; for (var i in obj) { console.log(i+":"+obj[i]); }; //output: //1:first //2:second //3:2 //4:1 //two:zoo //three:34
可发现,for...in 并不能够保证返回的是按一定顺序的索引,但是它会返回所有可枚举属性,包括继承属性。
给原型添加属性之后,默认情况下枚举,会把原型属性一并输出,如下所示。由于它总是会访问该对象的原型,看下原型上是否有属性,这在无意中就给遍历增加了额外的压力。
例:
function fun4(){ var a=[1,2,3,4,5]; Array.prototype.age=13; for(var i in a){ console.log("a["+i+"]: "+a[i]); } } //outuput: //a[0]: 1 //a[1]: 2 //a[2]: 3 //a[3]: 4 //a[4]: 5 //a[age]: 13
解决方法:
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames()
或执行 hasOwnProperty()
来确定某属性是否是对象本身的属性 (也能使用propertyIsEnumerable
)。
下面利用 hasOwnProperty()
的方法使隐藏的继承属性不会被显示。如果该对象是从原型链中继承了该属性,或者根本没有这样的一个属性,则返回false。如果某个对象具有给定名称的属性,则返回true。
function fun4(){ var a=[1,2,3,4,5]; Array.prototype.age=13; for(var i in a){ if( a.hasOwnProperty( i ) ) { console.log("a["+i+"]: "+a[i]); } } } //outuput: //a[0]: 1 //a[1]: 2 //a[2]: 3 //a[3]: 4 //a[4]: 5
在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。
Note: 意思就是尽量不要对数组对象使用for in遍历。