遍历如下的数组
let arr = [0, 1, 2, 3];
arr.length = 5;
delete arr[3];
arr.name = 'name';
arr.__proto__.id = 'id';
// arr => [0, 1, 2, empty, empty]
for
最传统的循环方法,也是速度最快的方法。
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 0 1 2 undefined undefined
}
for (let i = 0; i < arr.length; i++) {
if (i > 0) {
// break;
return false; // break 和 return false 可以中断循环
}
console.log(arr[i]); // 0
}
forEach
forEach
对数组中的每一个元素都执行一次回调函数。可以看做阉割版的 map
。
稀疏数组未被初始化的项或者被
delete
删除的项会被跳过。
forEach
不可以中断,但可以提前return
跳过。
arr.forEach((item) => {
console.log(item); // 0 1 2
});
arr.forEach((item, index) => {
console.log('start');
if (index > 0) {
return;
}
console.log(item); // start 0 start start
});
map
map
对数组中的每一个元素都执行一次回调函数,并用回调函数的返回值组成一个新数组返回,默认返回 undefined
。
稀疏数组未被初始化的项或者被
delete
删除的项会被跳过。
arr.map((item) => {
console.log(item); // 0 1 2
})
for in
for in
会对对象所有可枚举 (enumerable
)的属性都会变量,包括原型链上面的属性。
稀疏数组未被初始化的项或者被
delete
删除的项会被跳过。
for (let i in arr) {
console.log(arr[i]); // 0 1 2 name id
}
for (let i in arr) {
if (i > 0) {
break;
}
console.log(arr[i]); // 0
}
let obj = {
name: 'name',
number: 18
};
obj.__proto__.id = 'id2';
for (let i in obj) {
console.log(obj[i]); // name 18 id2
}
for of
for-of
语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。只要是一个可迭代(iterable
)的对象,就可以通过for-of
来迭代.
for (let value of arr) {
console.log(value); // 0 1 2 undefined undefined
}
for (let value of arr) {
if (value === 1) {
break;
}
console.log(value); // 0
}
for await ... of
function alarm(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(item);
resolve();
}, 2000);
});
}
for await (let value of arr) {
await alarm(value); // 0 1 2 undefined undefined,间隔两秒依次 log
}
function alarm(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(item);
resolve();
}, 2000);
});
}
for await (let value of arr) {
if (value === 1) {
break;
}
await alarm(value); // 0
}
测试速度
let arr = [];
for (let i = 0; i < 1000000; i++) {
arr[i] = i;
}
let length = arr.length;
console.time('for');
for (let i = 0; i < length; i++) {}
console.timeEnd('for');
console.time('forEach');
arr.forEach(() => {});
console.timeEnd('forEach');
console.time('map');
arr.map(() => {});
console.timeEnd('map');
console.time('forIn');
for (let i in arr) {
}
console.timeEnd('forIn');
console.time('forOf');
for (let value of arr) {
}
console.timeEnd('forOf');
在 2017 13" i5 MacBook Pro 的 Chrome 浏览器 79.0.3945.117
版本中,测试速度结果如下:
for: 3ms 左右 forEach: 12 ms 左右 map: 20 ms 左右 for in: 160 ~ 200 ms 左右 for of: 40 ms 左右
for | forEach | map | for in | for of | for await ... of |
---|---|---|---|---|---|
可遍历类型 | 本质是一个计数器,不负责遍历 | 数组 | 数组 | 对象的可枚举属性 | 可迭代对象 |
能否遍历空值 | 是 | 否 | 否 | 否 | 是 |
能否 break | 是 | 否 | 否 | 是 | 是 |
能否 continue | 是 | 否 | 否 | 是 | 是 |
能否获取索引 | 是 | 是 | 是 | 是 | 否 |
速度 | 1 | 2 | 3 | 5 | 4 |
特点 | 遍历对象及其原型链上的所有可枚举属性 |