回顾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