欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript for-in遍历,ES6的for-of遍历,可迭代对象的forEach()方法实例讲解

程序员文章站 2023-11-16 12:17:52
回顾for-in遍历 在js里,for-in遍历的是可迭代对象的key,这点需要特别注意: "use strcit"; var x=['lz&...

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