JavaScript for-in遍历,ES6的for-of遍历,可迭代对象的forEach()方法实例讲解
回顾for-in遍历
在js里,for-in遍历的是可迭代对象的key,这点需要特别注意:
"use strcit"; var x=['lz','h','is','a sb']; //array对象是可迭代的 for(let i in x){ console.log(i); //用for-in遍历输出看一下 }
输出
0 1 2 3
不方便之处
如果要获取它的值,就需要再去查询一次这个key所对应的值:
"use strcit"; var x=['lz','h','is','a sb']; //array对象是可迭代的 for(let i in x){ console.log(x[i]); //i是key,而x[i]就是i在x中对应的value }
输出
lz h is a sb
这种方法显然有些低效,而且语义上不是那么直观,我想要遍历的只是数组里的各个元素,为什么要使用key呢。
尝试遍历set时存在的问题
如果尝试用这种方式去遍历set,前面学了set可以看成只存储key的键值对系,但是却获取不到东西:
"use strcit"; var x=new set(['lz','h','is','a sb']); //set对象是可迭代的 for(let i in x){ console.log(i); //如果i视为object的key,尝试访问key去遍历set }
输出(没东西)
我认为这可能体现了set的无序性,总之没能遍历它。
尝试遍历map时存在的问题
map底层基于树来实现,它的key大抵也是无序的,没法遍历:
"use strcit"; var x=new map([[6,'lz'],[7,'h'],[7.5,'is'],[9.2,'a sb']]); //map对象是可迭代的 for(let i in x){ console.log(i); //如果i视为object的key,尝试访问key去遍历map的每个键 }
输出(没东西)
for-of遍历
用于set
for-of遍历对于set遍历的是集合中的值:
"use strcit"; var x=new set(['lz','h','is','a sb']); for(let i of x){ console.log(i); }
输出
lz h is a sb
用于map
for-of遍历对于map遍历的是键值对的array形式:
"use strcit"; var x=new map([[6,'lz'],[7,'h'],[7.5,'is'],[9.2,'a sb']]); for(let i of x){ console.log(i); }
输出
array [ 6, "lz" ] array [ 7, "h" ] array [ 7.5, "is" ] array [ 9.2, "a sb" ]
用于array
for-of遍历对于arrayt遍历的是其每个元素的值:
"use strcit"; var x=new array('lz','h','is','a sb'); for(let i of x){ console.log(i); }
输出
lz h is a sb
还有一些差异
在处理object对象时的差异
for-of是es6标准下的,在这之前就存在的for-in将object也视为可迭代对象,遍历出的是对象的各个属性和方法的名称:
"use strcit"; //为这个object对象添加了4个属性2个方法 var ok={ sb1:'lz', sb2:'h', sb3:'is', sb4:'a sb', myfun1:function(x,y){ return x+y; }, myfun2:function(x,y){ return x-y; } }; for(let i in ok){ console.log(i); }
输出
sb1 sb2 sb3 sb4 myfun1 myfun2
es6标准不认为object对象是可迭代的,只认map,set,array,所以不能用for-of遍历之:
"use strcit"; //object对象 var ok={ sb1:'lz', sb2:'h', sb3:'is', sb4:'a sb', myfun1:function(x,y){ return x+y; }, myfun2:function(x,y){ return x-y; } }; for(let i of ok){ console.log(i); //尝试用for-of遍历之 }
输出(报错)
typeerror: ok is not iterable
为可迭代对象添加成员时的差异
从for-in的角度来看,map和set遍历不了,object本来就是由各个成员变量和成员方法组成的,而for-in又认为object可迭代,添加成员能遍历是理所当然的。
所以添加成员时的差异只要去看array对象。
为array对象添加成员时,for-in会把这个成员和其它下标同一地视为key去遍历到:
"use strcit"; var ok=["lzh","is","rubbish","sb","big sb dog"]; ok.name="sblzh"; //为这个array对象添加一个成员变量 //为这个array对象添加一个成员方法 ok.myfun=function(x,y){ return x+y; }; //尝试用for-in遍历之 for(let i in ok){ console.log(ok[i]); }
输出
lzh is rubbish sb big sb dog sblzh function ok.myfun()
现在,如果只有for-in,被添加了成员的array对象变得很难用了。
而for-of会正确的区分成员和其内容:
"use strcit"; var ok=["lzh","is","rubbish","sb","big sb dog"]; ok.name="sblzh"; //为这个array对象添加一个成员变量 //为这个array对象添加一个成员方法 ok.myfun=function(x,y){ return x+y; }; //尝试用for-of遍历之 for(let i of ok){ console.log(i); //注意这里不需要ok[i]了,只要用一个i }
输出
lzh is rubbish sb big sb dog
可迭代对象的foreach()方法
foreach方法接收一个函数为参数,这样传进来的函数称为callback回调函数。
在每次迭代的过程中都会为这个函数传入一些参数来调用它一次,当然形参的名字是任意合法的都一样。用这个foreach()方法就可以把遍历+做事情写的非常简洁了。
对于object对象,es6已经明确指出它不是可迭代对象,object对象自然没有foreach()方法。
属于array对象的foreach()方法
"use strcit"; var ok=["lzh","is","rubbish","sb","big sb dog"]; var control=false; //用于控制只在第一次输出对象自己 ok.foreach( //传进来三个参数依次是(目前的元素值,目前的下标,本数组) function(now_element,now_index,thisarray){ //第三个参数每次迭代都一样的,只输出一次看一下就好 if(control===false){ control=true; console.log("这个array是"+thisarray); console.log("第3个参数的类型是"+typeof thisarray); } console.log("ok["+now_index+"]="+now_element); } );
输出
这个array是lzh,is,rubbish,sb,big sb dog 第3个参数的类型是object ok[0]=lzh ok[1]=is ok[2]=rubbish ok[3]=sb ok[4]=big sb dog
属于set对象的foreach()方法
注意在set对象上使用时传进来的前两个参数是完全一样的。
"use strcit"; var ok=new set(["lzh","is","rubbish","sb","big sb dog"]); var control=false; //用于控制只在第一次输出对象自己 ok.foreach( //传进来三个参数依次是(目前的元素值,目前的元素值,本集合) //毕竟set作为集合不涉及下标(无序),传进来的前两个参数都是元素值 function(now_element,now_elem,thisset){ //第三个参数每次迭代都一样的,只输出一次看一下就好 if(control===false){ control=true; console.log("这个set是"+thisset); console.log("第3个参数的类型是"+typeof thisset); } console.log("第1个参数="+now_element); console.log("第2个参数="+now_elem); } );
输出
这个set是[object set] 第3个参数的类型是object 第1个参数=lzh 第2个参数=lzh 第1个参数=is 第2个参数=is 第1个参数=rubbish 第2个参数=rubbish 第1个参数=sb 第2个参数=sb 第1个参数=big sb dog 第2个参数=big sb dog
属于map对象的foreach()方法
"use strcit"; var ok=new map([[7,"lzh"],[8.5,"is"],['666阿',"rubbish"],[-30,"sb"],[250,"big sb dog"]]); var control=false; //用于控制只在第一次输出对象自己 ok.foreach( //传进来三个参数依次是(目前的value,目前的key,本map) function(now_value,now_key,thismap){ //第三个参数每次迭代都一样的,只输出一次看一下就好 if(control===false){ control=true; console.log("这个set是"+thismap); console.log("第3个参数的类型是"+typeof thismap); } console.log("ok["+now_key+"]="+now_value); } );
输出
这个set是[object map] 第3个参数的类型是object ok[7]=lzh ok[8.5]=is ok[666阿]=rubbish ok[-30]=sb ok[250]=big sb dog