我们先来看下for
循环的4种不同遍历方式:
const arr = [10,20,30,40,50];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
arr.forEach((num,index)=> {
console.log(num,index)
});
for (const key in arr) {
if (Object.hasOwnProperty.call(arr, key)) {
console.log(arr[key])
}
}
for (const num of arr) {
console.log(num)
}
接下来就从几个不同的方面来说下这四种打印方式的区别。
遍历的目标:
for
循环:每层遍历需要通过下标来获取数组元素。forEach
:每层遍历可以直接拿到数组元素的值以及对应的下标。for-in
:每层遍历需要根据数组对象的键,来获得对应的值。for-of
:没层遍历可以直接拿到数组元素的值。我们来细说一下for-in
方式,我们看下下面这段代码打印出什么东西。
// 数组就是一个对象
const arr = [10, 22, 33, 44, 55];
// 对象可以通过.xxx的方式直接赋值一个属性
// 如果是普通的数组元素,那么对应的key就是数组的下标。
for (const key in arr) {
if (Object.hasOwnProperty.call(arr, key)) {
console.log('Key: ' + key, ', Value: ' + arr[key])
}
}
结果如下:
const arr = [10, , 55];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
console.log('*********************************************')
arr.forEach(num => {
console.log(num)
});
console.log('*********************************************')
for (const key in arr) {
if (Object.hasOwnProperty.call(arr, key)) {
console.log(arr[key])
}
}
console.log('*********************************************')
for (const num of arr) {
console.log(num)
}
输出结果如下:
结论如下:
for
循环,for-of
。forEach
、for-in
。我们先来写个简单的异步函数:
async function asyncMethod(num) {
setTimeout(() => {
console.log('hello')
}, 1000);
return num
}
我们来看下下面的案例:
for
循环调用案例:
const arr = [1, 2, 3];
async function test() {
const list = [];
for (let i = 0; i < arr.length; i++) {
const num = await asyncMethod(arr[i]);
list.push(num);
}
console.log(list);
return list;
}
{
(async () => {
await test();
})()
}
结果如下:
forEach
案例:
const arr = [1, 2, 3];
async function test2() {
const list = [];
arr.forEach(async (num) => {
const res = await asyncMethod(num);
list.push(res);
})
console.log(list);
return list;
}
{
(async () => {
await test2();
})()
}
for-in
案例:
const arr = [1, 2, 3];
async function test3() {
const list = [];
for (const key in arr) {
const num = await asyncMethod(arr[key]);
list.push(num);
}
console.log(list);
return list;
}
{
(async () => {
await test3();
})()
}
结果如下:
for-of
案例:
const arr = [1, 2, 3];
async function test4() {
const list = [];
for (const num of arr) {
const res = await asyncMethod(num);
list.push(res);
}
console.log(list);
return list;
}
{
(async () => {
await test4();
})()
}
结果如下:
可看出,只有forEach
这种写法,在同一个异步函数体内,无法同步获取到异步结果。 意思就是:
async function test(){
arr.forEach(async () => {
const 异步任务结果= await 异步任务();
})
这里想拿到上面forEach循环里面做的异步结果是不行的
doSomething()
}
但是,如果在函数题外面获取异步结果,例如:
async function test2() {
const list = [];
arr.forEach(async (num) => {
const res = await asyncMethod(num);
list.push(res);
})
return list;
}
{
(async () => {
const list = await test2();
console.log(list)
})()
}
此时无论哪一种写法,都是能获取到完整的list
的:
从遍历的目标来看:
for
:通过数组下标获取元素。forEach
:可直接获取元素以及对应的下标。for-in
:通过数组的键获取对应的值。(value = arr.key
)for-of
:可直接获取元素。从空属性的遍历来看:数组:arr = [1 , 2, ,3]
(注意有两个逗号)
for
:跳过空值。forEach
:不会跳过空值,会打印出undefined
。for-in
:不会跳过空值,会打印出undefined
。for-of
:跳过空值。从异步的结果的获取来看:
forEach
:无法在函数体内,获取forEach
里面的异步任务结果。函数体外可以。
for
:可以在函数体内,获取forEach
里面的异步任务结果。函数体外也可以。
for-in
:可以在函数体内,获取forEach
里面的异步任务结果。函数体外也可以。
for-of
:可以在函数体内,获取forEach
里面的异步任务结果。函数体外也可以。