JavaScript中的几种常用循环方式对比

JavaScript中的几种循环方式

1. for 循环

for循环是数组循环中最简单,也是最常用的循环方式。

1.1 使用方式

// 方式一:for循环
let arr1 = ['red','yellow','blue']
for(let i = 0; i < arr1.length; i++) {
    
    
  console.log(arr1[i])
}

在这里插入图片描述

1.2 不支持遍历对象(但不会报错)

注意:for循环对对象不生效,但是如果强行使用for循环对对象进行遍历,也不会报错,因为根本不会进入循环,相当于一段垃圾代码。

2. for-of 循环

2.1 使用方式

在这里插入图片描述
可以看到,如果数组循环中只使用到了数值(没使用索引),VSCode会建议我们使用更简单的循环方式for-of

// 方式二:for of 循环 
let arr1 = ['red','yellow','blue']
for(const element of arr1) {
    
    
  console.log(element)
}

在这里插入图片描述

2.2 for-of 和 for 循环比较(不允许修改原数组元素)

2.2.1 相同点

2.2.1.2 都可以遍历数组,但不允许遍历对象

2.2.1.2 都支持 break 和 continue 结束整个/单次循环

(1)break

let arr1 = ['red','yellow','blue']
for(let element of arr1) {
    
    
  console.log('element', element)
  if(element === 'yellow') {
    
    
    break
  }
}
console.log('arr1', arr1)

在这里插入图片描述

(2)continue

let arr1 = ['red','yellow','blue']
for(let element of arr1) {
    
    
  console.log('element', element)
  if(element === 'yellow') {
    
    
    continue
  }
  console.log('continue', element)
}
console.log('arr1', arr1)

在这里插入图片描述

2.2.2 不同点

2.2.2.1 for-of 强行遍历对象,会报错

for-of强行遍历对象,会报错

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
for(const element of obj1) {
    
    
  console.log(element)
}

在这里插入图片描述

2.2.2.2 不允许直接修改数组内容

for(let element of arr1) {
    
    
  element = 'test'
  console.log('element', element)
}
console.log('arr1', arr1)

在这里插入图片描述

可以看到,即使在for-of修改了元素的值,原数组的值仍然不受任何影响。可以理解为,for-of循环的element只是复制了一份数组的元素提供使用。

2.2.2.3 允许修改数组元素的属性(如果元素是对象的话)

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
for(let element of objArr) {
    
    
  element.name = 'me'
  console.log('element', element)
}
console.log('objArr', objArr)

在这里插入图片描述

3. for-in 循环(支持并且建议用来遍历对象,而非数组)

3.1 使用方式

3.1.1 遍历对象

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
// 方式三:for-in 循环
for (const key in obj1) {
    
    
  console.log(key, obj1[key])
}

在这里插入图片描述

3.1.2 遍历数组

let arr1 = ['red','yellow','blue']
for (const key in arr1) {
    
    
  console.log(key, arr1[key])
}

在这里插入图片描述

3.2 for-in 和 for 循环比较

3.2.1 相同点

3.2.1.1 都可以遍历数组

3.2.1.2 都支持 break 和 continue 结束整个/单次循环,但是for-in还支持对对象进行操作

(1)break

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
for (const key in obj1) {
    
    
  console.log(key, obj1[key])
  if(key === 'age') {
    
    
    break
  }
}

在这里插入图片描述
(2)continue

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
for (const key in obj1) {
    
    
  console.log(key, obj1[key])
  if(key === 'age') {
    
    
    continue
  }
  console.log('continue', key)
}

在这里插入图片描述

3.2.2 不同点

3.2.2.1 可以遍历对象

3.2.2.1 不建议用来遍历数组,key值是string类型

虽然for-in也可以遍历数组,但是从遍历的结果可以看出,其实for-in是把数组当成对象去遍历的。

通常谷歌浏览器在控制台输出数字时,是蓝色的。而在输出字符串时,是绿色的。从这一点也能佐证。

for (const key in arr1) {
    
    
  console.log(key, arr1[key], typeof key)
}

在这里插入图片描述
因此,不建议遍历数组使用for-in,或者在需要使用key时,包一层Number(key),避免一些特殊判断时报错。

4. forEach 循环(Array.prototype 数组原型上的方法)

在这里插入图片描述
在这里插入图片描述

4.1 使用方式

let arr1 = ['red','yellow','blue']
// 方式四:forEach 循环
arr1.forEach((val, index, arr) => {
    
    
  console.log(val, index, arr)
});

在这里插入图片描述

4.2 和 for 循环比较

4.2.1 相同点:都可以遍历数组,并且直接通过数组下标改变元素值

let objArr = [
{
    
    
   name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
objArr.forEach((item, index, arr) => {
    
    
  objArr[index] = 'Bruce'
});
console.log('objArr', objArr)

在这里插入图片描述

4.2.2 不同点

4.2.2.1 无法直接通过第一个参数修改元素值

第一个参数和第三个参数只是复制元素和数组,并非本身。所以直接修改,不会影响数组本身。

let arr1 = ['red','yellow','blue']
arr1.forEach((val, index, arr) => {
    
    
  console.log(val)
  val = 'green'
  arr = []
});
console.log('arr1', arr1)

在这里插入图片描述

4.2.2.2 数组的元素是对象的话,可以直接修改对象属性的方式

不过如果元素值是对象的话,可以通过修改对象属性的方式修改(因为复制的是元素是该对象的引用,相当于复制了房间号,房间里的东西可以改变,但是房间号仍然不变)。

let objArr = [
{
    
    
   name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
objArr.forEach((item, index, arr) => {
    
    
  item.name = 'Bruce'
});
console.log('objArr', objArr)

在这里插入图片描述

4.2.2.3 不能遍历对象,强行调用会报错

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
obj1.forEach((item, index, arr) => {
    
    
  console.log(item, index, arr)
});

在这里插入图片描述

4.2…2.4 不能使用 break 和 continue,会导致语法错误

在这里插入图片描述
在这里插入图片描述

5. map 循环(Array.prototype 数组原型上的方法)

5.1 使用方式:遍历原数组,通过映射生成新数组(元素数量不变,值变化)

let arr1 = ['red','yellow','blue']
arr1.map((item, index, arr) => {
    
    
  console.log(item, index, arr)
})

在这里插入图片描述

5.2 和 forEach 循环进行比较

因为都是Array原型链上的方法,所以直接与 forEach 循环方式进行比较更为合适。

5.2.1 相同点

5.2.1.1 都有3个参数,都是(currentValue, index , arr)

5.2.1.2 都无法直接通过currentValue修改原数组

5.2.1.3 都可以通过 index 配合 arr(或者原数组)直接修改元素值

5.2.2 不同点

5.2.2.1 map 循环会返回一个新的数组,forEach不会

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
let nameArr = objArr.map(item => {
    
    
  return item.name
})
console.log('nameArr:', nameArr)

let ageArr = objArr.map(item => 
  item.age + 1
)
console.log('ageArr:', ageArr)

console.log('objArr:', objArr)

在这里插入图片描述

虽然使用 .map 方法可以帮助我们基于原数组快速生成一个新的数组,但是仍然要注意,当原数组元素是对象时,仍然会有修改原数组的风险。

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
let ageArr = objArr.map(item => 
  item.age = item.age + 1
)
console.log('ageArr:', ageArr)

console.log('objArr:', objArr)

在这里插入图片描述
建议使用.map方法生成新数组时,不要对原数组元素进行新的赋值操作,

let ageArr = objArr.map(item => 
  item.age + 1
)

等价于

let ageArr = objArr.map(item => {
    
    
  return item.age + 1
})

建议初学者不要使用省略写法,避免理解上的误差。

6. filter 循环(Array.prototype 数组原型上的方法)

6.1 使用方式:遍历原数组,筛选元素,组成新的数组(元素个数变化,值不变)

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
// 方式五: filter 循环
let newArr = objArr.filter((item, index, arr) => {
    
    
  return item.age > 20
})
console.log('newArr', newArr)

在这里插入图片描述

6.2 和 map 循环进行比较

6.2.1 相同点

6.2.1.1 都有3个参数,都是(currentValue, index , arr)

6.2.2 不同点

6.2.2.1 功能侧重不同,filter筛选元素(新数组元素个数变化,值不变),map是映射元素(新数组元素个数不变,值变化)

(1)filter是在通过条件筛选出原数组的部分元素,复制到新数组中,因此新数组的元素个数小于等于原数组,并且返回的元素值不变。
(2)map是遍历原数组,取每个元素或者元素中的属性,进行或者不进行处理,获得新的元素,之后再一一填充到新数组。因此新数组的元素个数等于原数组,但是返回的元素值通常会发生变化。

7. some 循环(Array.prototype 数组原型上的方法)

7.1 使用方式:遍历数组,只要有一个元素符合条件,返回true,否则返回false

let objArr = [
  {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
// 方式七:some 循环
let checkAge = objArr.some((item, index, arr) => {
    
    
  return item.age > 26
})
console.log('checkAge', checkAge)

let checkName = objArr.some((item, index, arr) => {
    
    
  return item.name === 'Mick'
})
console.log('checkName', checkName)

在这里插入图片描述

7.2 和 forEach、map 、filter 循环进行比较

7.2.1 相同点

7.2.1.1 都有3个参数,都是(currentValue, index , arr)

7.2.1.2 都无法直接通过currentValue修改原数组

7.2.1.3 都可以通过 index 配合 arr(或者原数组)直接修改元素值

7.2.2 不同点

7.2.2.1 功能侧重不同:some循环是寻找数组中是否有元素符合条件

8. every 循环(Array.prototype 数组原型上的方法)

8.1 使用方式:遍历数组,只有当所有元素都符合条件返回true,否则返回false

et objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
// 方式八:every循环
let allAdult = objArr.every((item, index, arr) => {
    
    
  return item.age >= 20
})
console.log('allAdult', allAdult)

let allMale = objArr.every((item, index, arr) => {
    
    
  return item.sex === 'male'
})
console.log('allMale', allMale)

在这里插入图片描述

8.2 和 some 循环比较(大家都懂,就不说了吧)

9. reduce 循环(Array.prototype 数组原型上的方法)

9.1 使用方式

9.1.1 遍历数组,作为累加器使用

// 方式九:reduce循环
let numArr = [11, 13, 15, 17, 19]
let totalNum = numArr.reduce((total, item, index , arr) => {
    
    
  console.log(total, item, index, arr)
  return total + item
})
console.log('totalNum', totalNum)

在这里插入图片描述
reduce方法一共有4个参数,total:初始值,item:当前元素,index:当前索引,arr:遍历的数组
可以看到,我们第一次累加时,初始值为第一个元素,当前元素和索引是第二个。因此在处理时,如果元素是对象,注意累加时记得处理。

9.1.2 支持传入初始值(例子:去重函数)

array.reduce(function(total, item, index, arr), initialValue)
let repeatArr = [
  {
    
     id: 1, name: 'Tom'},
  {
    
     id: 2, name: 'Jack'},
  {
    
     id: 1, name: 'Tom'},
  {
    
     id: 3, name: 'Mike'},
  {
    
     id: 3, name: 'Mike'},
  {
    
     id: 2, name: 'Jack'},
]

function getUniqueArr(array) {
    
    
  let idObj = {
    
    }
  return array.reduce((pre, item, index ,arr) => {
    
    
    if(!idObj[item.id]) {
    
    
      idObj[item.id] = true
      return [...pre, item]
    } else {
    
    
      return pre
    }
  }, [])
}
console.log('uniqueArr', getUniqueArr(repeatArr))

在这里插入图片描述
传入初始值 [ ],第一次的 total, item, index 就变成了[], { id: 1, name: 'Tom'}, 0

9.2 和其他数组原型链循环方式比较

9.2.1 相同点

9.2.1.1 都有当前元素、当前索引、数组 3个参数

9.2.2 不同点

9.2.2.1 作为累加器,增加了 total 和 initialValue 两个参数

9.2.2.1 可以函数中处理新数组的元素个数和元素值(基于原数组创建一个元素个数和值都有变化的新数组时,非常好用)

10. reduceRight 循环(Array.prototype 数组原型上的方法)

10.1 使用方式:和reduce功能一样,只是遍历顺序相反

array.reduceRight(function(total, item, index, arr), initialValue)
let arr1 = ['red','yellow','blue', 'green']
let namesStr = arr1.reduceRight((total, item, index, arr) => {
    
    
  console.log(total, item, index)
  return total + ',' + item
})

console.log('namesStr', namesStr)

在这里插入图片描述

11. while 循环

11.1 使用方式

let arr1 = ['red','yellow','blue', 'green']
let i = 0
while(i < arr1.length) {
    
    
  console.log(arr1[i])
  i++
}

在这里插入图片描述

11.2 和其他循环比较

11.2.1 相同点

11.2.1.1 都可以遍历数组

11.2.2 不同点

11.2.2.1 可以自定义遍历条件,更加灵活

11.2.2.2 可以随意对数组进行处理

11.2.2.3 作为遍历条件的参数大多数情况下会成为全局变量,需要注意命名,避免重名影响其他变量

12. do while 循环

12.1 使用方式

let i = 0
do {
    
    
  console.log(arr1[i])
  i++
} while(i < arr1.length)

在这里插入图片描述

12.2 和 while 循环比较 :无论如何都会执行第一次循环

13. 综合上述

不同循环方式都有其优势和劣势,我们应该根据具体场景使用。

13.1 遍历数组,for 循环功能最完善

遍历数组,最经典也是最好用的就是 for 循环,功能最全。如果觉得记忆太麻烦,记住这一种遍历方式即可。

13.2 遍历对象,使用 for-in 循环(不建议遍历数组)

遍历对象,使用 for-in 循环,虽然for-in也支持遍历数组,但是更加适合遍历对象;

let obj1 = {
    
    
  name: 'Sheldon',
  age: 26,
  sex: 'male'
}
// 方式三:for-in 循环
for (const key in obj1) {
    
    
  console.log(key, obj1[key])
}

13.3 遍历对象数组,需要break或者continue时,可使用 for-of 循环

遍历对象数组,并且当数组数据量过大,需要从循环中break或者continue释放出来时,使用 for-of 循环;

let arr1 = ['red','yellow','blue']
for(let element of arr1) {
    
    
  console.log('element', element)
  if(element === 'yellow') {
    
    
    break
  }
}
console.log('arr1', arr1)

13.4 遍历对象数组,不需要break或者continue时,使用 array.forEach 循环

let arr1 = ['red','yellow','blue']
// 方式四:forEach 循环
arr1.forEach((val, index, arr) => {
    
    
  console.log(val, index, arr)
});

13.5 筛选元素,使用array.filter 循环

(5)筛选符合条件的元素生成新数组时,使用 array.filter 循环

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
// 方式五: filter 循环
let newArr = objArr.filter((item, index, arr) => {
    
    
  return item.age > 20
})
console.log('newArr', newArr)
## 13.6 

13.6 修改元素生成新数组,使用 array.map 循环

基于原数组修改数据生成新数组时,使用 array.map 循环

let objArr = [
 {
    
    
    name: 'Sheldon',
    age: 26,
    sex: 'male'
  }, {
    
    
    name: 'Jane',
    age: 20,
    sex: 'female'
  }, {
    
    
    name: 'Mick',
    age: 24,
    sex: 'male'
  },
]
let nameArr = objArr.map(item => {
    
    
  return item.name
})
console.log('nameArr:', nameArr)

let ageArr = objArr.map(item => 
  item.age + 1
)
console.log('ageArr:', ageArr)

console.log('objArr:', objArr)

13.7 累加数值,或者处理元素个数和内容时,使用 array.reduce 循环

作为累加器或者需要对数组的个数和值进行处理时,使用 array.reduce 循环

// 方式九:reduce循环
let numArr = [11, 13, 15, 17, 19]
let totalNum = numArr.reduce((total, item, index , arr) => {
    
    
  console.log(total, item, index, arr)
  return total + item
})
console.log('totalNum', totalNum)
array.reduce(function(total, item, index, arr), initialValue)
let repeatArr = [
  {
    
     id: 1, name: 'Tom'},
  {
    
     id: 2, name: 'Jack'},
  {
    
     id: 1, name: 'Tom'},
  {
    
     id: 3, name: 'Mike'},
  {
    
     id: 3, name: 'Mike'},
  {
    
     id: 2, name: 'Jack'},
]

function getUniqueArr(array) {
    
    
  let idObj = {
    
    }
  return array.reduce((pre, item, index ,arr) => {
    
    
    if(!idObj[item.id]) {
    
    
      idObj[item.id] = true
      return [...pre, item]
    } else {
    
    
      return pre
    }
  }, [])
}
console.log('uniqueArr', getUniqueArr(repeatArr))

猜你喜欢

转载自blog.csdn.net/qq_39055970/article/details/132063319