前情提要
刚刚接触到js写for循环的时候,觉得for(i in array)这种格式简直是非常直观,比三段论的for循环好写得多。直到遇到了一个坑,事情是这样的:
最开始的网页中,鉴于方便,清一色使用的是for(i in array)的格式,直到后来出于需求,在前面用Array.prototype写了一个新方法(新方法用来找出多个索引,以往的indexOf只能找出一个),后来发现之前所有写了for(i in array)的地方在最后统统多出一条undefined。
一、情况的发现:自己写了个Array.prototype到底写到哪了?
先写一个没有写新方法的array,用for…in循环console.log以下:
代码段:
<script>
var a = [11,12,13,14,15];
for(i in a){
console.log(a[i]);
}
</script>
控制台显示结果(前面的test.html:27表示执行代码的位置,不是console.log产生的)
test.html:27 11
test.html:27 12
test.html:27 13
test.html:27 14
test.html:27 15
此时,script中再加入Array.prototype引入新方法:
Array.prototype.anyfunction = function(){
var a = "这个代码段啥也没干,就占用了你的内存";
}
var a = [11,12,13,14,15];
for(i in a){
console.log(a[i]);
}
再次显示在控制台是这个样子:
test.html:30 11
test.html:30 12
test.html:30 13
test.html:30 14
test.html:30 15
test.html:30 ƒ (){
var a = "这个代码段啥也没干,就占用了你的内存";
}
也就是说,他把我写的函数好像放到了数组里面。但是当我去寻找数组a.length时,两次的结果都是5,这是怎么一回事呢?
以下内容是我的一些理解和拙见,希望专业人士能够提出一些宝贵意见
二、Array也是一个Object
遥想前一阵,刚学js的时候,视频里面说: “实际上JavaScript的数据类型除了几个基本类型string、boolean、number、Null、Undefined和symbol之外,什么date啊、array啊、剩下的全都是对象。” 当时对于这句话并没有很深的理解。但是回顾这个例子,仿佛了解了一些:
既然是对象(object),那么就应该有属性和方法。拿这个array为例,他是一个对象,但是他的方法里面没有我需要的方法,我总不能去改Array构造函数内部的方法吧,怎么办呢?
三、通过prototype创建的属性方法
那就只能用prototype来创建。
Array.prototype.你需要的方法名 = function(...){...}
这个prototype到底创建了什么?我们不妨自己创建一个构造函数试试:
function Namelist(){
this.name1='张一';
this.name2='李二';
this.name3='王三';
}
var MyOwnNamelist = new Namelist;
for(i in MyOwnNamelist){console.log(i)}
得到的结果是:
test.html:31 name1
test.html:31 name2
test.html:31 name3
而如果我们在创建MyOwnNamelist之前,加入一句
Namelist.prototype.name4 = '赵四';
那么结果就变成了
test.html:32 name1
test.html:32 name2
test.html:32 name3
test.html:32 name4
当我们console.log(MyOwnNamelist)时,控制台显示如下:
Namelist {name1: '张一', name2: '李二', name3: '王三'}
name1: "张一"
name2: "李二"
name3: "王三"
[[Prototype]]: Object
name4: "赵四"
constructor: ƒ Namelist()
[[Prototype]]: Object
可以看出,新添加的name4:‘赵四’,是添加到[[Prototype]]里面,但是for…in可以遍历到。这不禁让我想起我的那一堆数组,在创建一个prototype之后,数组本身的内容没有增加,但是创建的东西却都多遍历了一遍?
四、数组遍历用for…in ?!劝你别这么干!!
上网查了一下js中的in关键字:
“JavaScript中的in 操作符是对Object(对象)操作的,并不是针对数组。”
也就是说,Object.prototype实际上是添加了一个属性或者方法,添加的位置是[[Prototype]]中,而for…in会将添加进去的东西也遍历到。所以在数组中使用for…in循环的时候,数到后面,i的值会大于数组的长度,这是如果我们取 array[ i ],就会出现undefined。。。
但是for(i=0;i<array.length;i++)这种方式则是调用了.length,这是不会查到Object.prototype添加的属性方法的,因此对于数组,我建议大家老老实实,尽量不要用for…in。。。
不说了,我通篇的数组for循环用的都是for…in,我要一个一个改去了…