在日常开发过程中,高频使用的语句如果for循环说自己是第二,则没人敢称第一。这篇文章我们来详细看下for循环在各个场景中的使用。
1.遍历普通数组
当需要用到break、continue或者return时,可以使用for( i=0 ... i++ )和for ... of,但是不能使用forEach
break和continue
let arr = [0,1,2,3, ,5]
for(let i = 0; i < arr.length; i ++) {
if(arr[i] === 3) {
break // 0 1 2
// continue // 0 1 2 undefined 5
}
console.log(arr[i])
}
for(let item of arr) {
if(item === 3) {
break // 0 1 2
// continue // 0 1 2 undefined 5
}
console.log(item)
}
arr.forEach((item, index, arr) => {
if(item === 3) {
break // 0 1 2 3 5
}
console.log(item)
})
函数return
let arr = [0,1,2,3, ,5]
function f(arr) {
arr.forEach((item, index, arr) => {
if(item === 3) {
return // 0 1 2 5
}
console.log(item)
})
}
f(arr)
let arr = [0,1,2,3, ,5]
function f(arr) {
for(let item of arr) {
if(item === 3) {
return // 0 1 2
}
console.log(item)
}
}
f(arr)
特点总结
- for( i=0 ... i++ )遍历数组的索引,for ... of遍历数组的元素,forEach可以同时遍历索引、元素和数组
- for( i=0 ... i++ )和for ... of可以被break和continue结束或中断循环,也可以通过return返回结束函数,forEeach则不受break和continue的影响,不能通过return返回结束函数
- for( i=0 ... i++ )和for ...of遇到元素为空仍会执行本次循环,而forEach遇到空元素会不执行本次循环
使用场景总结
- 如果需要return或者break,选for ... of 或 for( i=0 ... i++ )
- 如果需要index,但不需要return或者break, 选forEach 或 for( i=0 ... i++ )
- 如果需要index, 且需要return或者break, 选for( i=0 ... i++ )
2. this的指向问题
let arr = [0,1,2,3, ,5]
for(let i = 0; i < arr.length; i ++) {
console.log(this) // window
}
for(let item of arr) {
console.log(this) // window
}
arr.forEach((item, index, arr) => {
console.log(this) // window
})
arr.forEach(function(item, index, arr) {
console.log(this) // undefined
})
当forEach里面如果用的是普通函数,则是不能初始化this的,其他情况下均可以初始化this。
总结:forEach里不要使用this
3. 异步处理情况 async/await
用setTimeout模拟异步执行的方法
passOrFailed (i) {
return new Promise((resolve) => {
// 异步操作
setTimeout(() => {
console.log(`${i}成功`)
resolve()
}, 1000)
})
},
在test ()函数里循坏遍历去调用,期望是第一个循环里的内容全部执行完,再去执行下一次循环
async test () {
const arr = [1, 2, 3, 4, 5]
for (let i = 0; i < arr.length; i++) {
console.log(`${i}start`)
await this.passOrFailed(i)
console.log(`${i}end`)
}
}
期望的结果是这样的
// 0start
// 0成功
// 0end
// 1start
// 1成功
// 1end
// ...
下面我们直接看下完整代码
3.1 for( i=0 ... i++ )
// a.vue
<script>
export default {
methods: {
passOrFailed (i) {
return new Promise((resolve) => {
// 异步操作
setTimeout(() => {
console.log(`${i}成功`)
resolve()
}, 1000)
})
},
async test () {
const arr = [1, 2, 3, 4, 5]
for (let i = 0; i < arr.length; i++) {
console.log(`${i}start`)
await this.passOrFailed(i)
console.log(`${i}end`)
}
}
},
mounted () {
console.log('start!!!')
this.test().then(() => { console.log('end!!!') })
}
}
</script>
3.2 for ... of
// a.vue
<script>
export default {
data () {
return { }
},
methods: {
passOrFailed (i) {
return new Promise((resolve) => {
// 异步操作
setTimeout(() => {
console.log(`${i}成功`)
resolve()
}, 1000)
})
},
async test () {
const arr = [1, 2, 3, 4, 5]
for (const item of arr) {
console.log(`${item}start`)
await this.passOrFailed(item)
console.log(`${item}end`)
}
}
},
mounted () {
console.log('start!!!')
this.test().then(() => { console.log('end!!!') })
}
}
</script>
for( i=0 ... i++ )和for ... of的输出结果是一样的
3.3 forEach
如果像这样按照上面的写法直接改成forEach,编译会报错
// a.vue
async test () {
const arr = [1, 2, 3, 4, 5]
arr.forEach(item => {
console.log(`${item}start`)
await this.passOrFailed(item)
console.log(`${item}end`)
})
}
我们需要改成这样的写法
// a.vue
<script>
export default {
data () {
return { }
},
methods: {
passOrFailed (i) {
return new Promise((resolve) => {
// 异步操作
setTimeout(() => {
console.log(`${i}成功`)
resolve()
}, 1000)
})
},
test () {
const arr = [1, 2, 3, 4, 5]
arr.forEach(async item => {
console.log(`${item}start`)
await this.passOrFailed(item)
console.log(`${item}end`)
})
}
},
mounted () {
console.log('start!!!')
this.test()
console.log('end!!!')
}
}
</script>
得到的结果和我们逻辑上期望的不一样的
所以当涉及到异步操作时,尽量不要使用forEach
4. 总结
不同场景下for循环的使用情况总结如下
我们看到最原始的for( i=0 ... i++ )是使用于所有场景的,但是代码量会相对多一点,forEach写起来代码量是比较少的,也更直观,但是使用的局限性也比较大,注意不是所有场景都可以用的哦。还是要根据不同的场景使用不同的循坏。
如果觉得文章对你有用,就点个赞再走吧,笔芯~