17年5月更 js中的for循环

来源:互联网 发布:金融投资网络销售好吗 编辑:程序博客网 时间:2024/06/06 19:50

之前的认识中,没有注意到for-of循环,也没有写foreach循环

现在重新来总结一下js里面关于for循环的用法

在ES5中,关于for循环只有三种:

  • 普通的for循环
  • for…in
  • forEach迭代

在ES6中,新增了一个for循环:

  • for…of

普通的for循环

const arr = [1, 2, 3, 4, 5];for(let i = 0,len = arr.length; i < len; i++){    console.log(arr[i]);}// 1, 2, 3, 4, 5

for-in

通常情况下,我们很少用for-in来遍历数组,因为for-in遍历的是数组索引。

const arr = [1, 2, 3 ,4 ,5]for(let v in arr){    console.log(arr[v]);}// 1, 2, 3, 4, 5

不对不对不对!!!!!!!
重要的事情还是说三遍!

经过在MDN上查阅,发现for-in遍历的不是数组的索引,而是遍历可枚举属性。
而数组的索引正是可枚举的整数名,所以我们之前可以使用for-in来遍历数组。
但是for-in 不应该去遍历一个对下标顺序很重要的Array。因此当迭代那些对访问次序重要的Array的时候,我们可以使用forEach和for-of(这两个随后会说)。

但是for-in难道就真的不适合遍历数组了么????

for-in可能在绝大多数的场景上,不如其他循环好用,因为性能差,属性顺序不准确。但是在遍历一些稀疏数组的时候,for-in是绝对好用的。

还是看图吧。

这里写图片描述

这里写图片描述

我们可以很清楚的看到,只有for-in在遍历稀疏数组的时候,只遍历真实存在的值。

所以通常我们仅在遍历对象的时候使用for-in循环。

const obj = {a: 1, b: 2, c: 3};for(let v in obj){    console.log(`obj.${v} = ${obj[v]}`);}// obj.a = 1// obj.b = 2// obj.c = 3

针对所说的for-in遍历的是可枚举属性
那么:在原型上的属性,for-in也是可以遍历的到的。

const obj = {a: 1, b: 2, c: 3};function Color(){    this.color = 'red';}Color.prototype = obj;let newObj = new Color;for(let v in newObj){    console.log(v);}// color, a, b, c

可以看出,for-in是可以对一切可枚举的属性进行遍历的,包括原型链上的属性。但是那么通常我们并不希望获取原型链上的属性。
那么我们可以使用 hasOwnProperty()方法。该方法返回一个布尔值,表示对象是否具有指定的属性作为自身属性。

这样我们可以把之前的例子进行修改:

let obj = {a: 1, b: 2, c: 3};function Color(){    this.color = 'red';}Color.prototype = obj;let newObj = new Color();for(let v in newObj){    if(newObj.hasOwnProperty(v)){        console.log(v);    }}// color

eg: 这里要多说一句哦,这个for-in是ES3 就推出的专门来遍历对象属性的,但是发现更多的需求其实是并不需要遍历原型链上的属性,所以ES5就推出了专门来遍历对象上自身属性的方法——Object.keys()

在ES2017中,已经配套的把Object.values和Object.entries来遍历值,和键值。
但是这三个方法返回的都是数组,需要配合for-of循环来使用。

forEach

在ES5中,引入了一个专门迭代Array的方法,即forEach循环。
其实引入了五个,比如:

  • forEach() 对数组中的每一项运行给定函数,没有返回值。
  • filter() 对数组中的每一项运行给定的函数,返回为true的项组成的数组。
  • map() 对数组中的每一项运行给定的函数,返回函数运行后组成的数组。
  • every() 对数组中每一项运行给定函数,若每一项都为true,则返回true。
  • some() 对数组中的每一项运行给定函数,若其中有一项为true,则返回true。

他们都可以传入三个参数,分别是
item,index,array

const arr = [1, 2, 3];arr.forEach((data) => {    console.log(data);})// 1, 2, 3

for-of

已经有了for-in,for,forEach,为什么要ES6还要搞出来个for-of呢?
这是因为之前的循环,各有各的缺点。
那说说for-of好在哪里吧:

  1. 不仅支持遍历数组,还可以遍历字符串,类数组对象,Map,Set等。
  2. 避开了for-in的各种缺陷。
let arr = [100, 200, 300];for(let i = 0; i < arr.length; i++){    console.log(arr[i]);}for(let i in arr){    console.log(arr[i]);}for(let i of arr){    console.log(i);}

可以看出,使用for-of循环是最简单的。for-in并不可靠。

但是,for-of在遍历普通对象的时候就力不从心了。

let obj = {a: 1, b: 2, c: 3};for(let i of obj){    console.log(i);}// 报错for(let i in obj){    console.log(i);}// a, b, c

总结:
for 是只能处理Array,性能好,但是有时候代码量较大。

for-in 为遍历对象而设计,但又能比较好的去处理稀疏数组。在遍历对象的时候却又会遍历到原型链上的属性,所以常常用hasOwnProperty来进行过滤。但现在可以使用Object.keys来替代for-in+hasOwnProperty

forEach 是为迭代Array而设计,对Array中的每一项都运行给定的函数。

for-of 是为了之前的for循环中的弊端所做的补救。for-of规避了for-in的缺点,并且还可以去遍历类数组对象。但是for-of并不能适用于普通对象。对于普通对象,还是使用for-in靠谱。

1 0