说一下for,forEach,for of,for in以及区别

289 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

前言

我们从解决下面问题来区分for,forEach,for of,for in:
如何遍历数字下标的数组或类数组对象? 比如有两个需求:

  1. 用一组索引数组实现课程表;
  2. 定义函数实现计算任意多个数的和;

普通for循环

需求一:课程表--可以实现;

var arr = ['语文', '英语', '数学', '体育', '音乐', '美术', '化学'];
for (var i = 0; i < arr.length; i++) {
    console.log(`第${i+1}节课是:${arr[i]}`);
}

需求二:定义函数实现计算任意多个数的和--可以实现;

function add() {
    //arguments[   ]
    var result = 0;
    for (var i = 0; i < arguments.length; i++) {
        result += arguments[i];
    }
    return result;
}
console.log(add(1,2,3)); //6
console.log(add(1,2,3,5)); //11

普通for循环的优缺点

优点:既可以遍历索引数组,又可以遍历类数组对象(arguments),只要下标是数字
缺点:没有可简化的空间

forEach

没有返回值,不改变原数组

var arr=['语文','英语','数学','体育','音乐','美术','化学'];
arr.forEach(function(name,index){
    console.log(`第${index + 1}节课是:${name}`)
})

可更简化:

var arr=['语文','英语','数学','体育','音乐','美术','化学'];
arr.forEach((name,index)=> {
    console.log(`第${index + 1}节课是:${name}`)
})

需求二:定义函数实现计算任意多个数的和--无法实现;

function add() {
    //arguments[   ]
    var result = 0;
    //这里会报错,arguments.forEach is not function
    arguments.forEach((m)=>{
        result += m;
    })
    return result;
}
console.log(add(1,2,3)); //6
console.log(add(1,2,3,5)); //11

这里会报错,arguments.forEach is not function;
因为:forEach是个数组类型函数,但arguments不是数组类型对象,所以无权使用数组类型函数;

forEach优缺点

优点:可以配合es6的箭头函数,简化代码
缺点:只能遍历数组下标的索引数组,无法遍历类数组对象
解决:
使用for of

for of

es6新增的特性,for...of可以循环读取键值,如果要通过for...of循环,获取数组的索引,可以借助数组实例的entries方法和keys方法

for(var 元素值m of 索引数组/类数组对象){  
  //of会依次取出索引数组/类数组对象中每个属性值  
  //自动保存在of前的变量中
}

需求一:

for(var [index,name] of arr.entries()){
    console.log(`第${index + 1}节课是:${name}`)
}
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x = fruits.entries();
console.log(x.next().value)
 //[0, 'Banana']

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x = Object.entries(fruits);
console.log(x)
//[['0''Banana']['1''Orange']['2''Apple']['3''Mango']]

image.png 需求二:

function add() {
    //arguments[   ]
    var result = 0;
    for(var m of arguments){
        result += m;
    }
    return result;
}
console.log(add(1,2,3)); //6
console.log(add(1,2,3,5)); //11

for of的问题

  • 无法获得下标位置i,只能获得元素值,对于数组借助entries方法和keys方法只返回数字索引的属性,对于类数组对象,因为不能使用;
function add() {
    //arguments[   ]
    var result = 0;
    for(var [index,m] of arguments.entries()){
        result += m;
    }
    return result;
}
console.log(add(1,2,3)); //6
console.log(add(1,2,3,5)); //11

image.png
会报错,因为entries是数组的实例方法;

  • 无法控制遍历的顺序或步调,只能从头到尾,一个挨一个的顺序遍历;
  • 无法遍历下标名为自定义的对象和关联数组;
    但是:
    因为数组绝大多数都是数字下标,绝大多数也是从头到尾一个挨着一个遍历的,且绝大多数循环不太关心下标位置,之关心元素值,所以for of用的还是比较多的。

for in

JavaScript原有的for...in循环。

let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) {
  console.log(i); //  "3", "5", "7"
}

上面的官方例子就可以看出for of和for in的区别;
上面代码中,for...of循环不会返回数组arrfoo属性,而for in可以,并且for...in,只能获得对象的键名,不能直接获取键值,而ES6提供for...of循环,允许遍历获得键值。

总结for,forEach,for of,for in的区别

image.png
总结:

  • 下标为数字,首选for of;
  • 下标为自定义字符串,首选for in;