对比性能
var arr = new Array(999999).fill(0)
let i = 0,
arrLength = arr.length;
console.time('for~循环');
for (; i < arrLength; i++) { }
console.timeEnd('for~循环');
// for~循环: 4.461181640625 ms
console.time('while~循环');
var _i = 0
while (_i < arr.length) {
_i++
}
console.timeEnd('while~循环');
// while~循环: 3.11474609375 ms
console.time('forEach~循环');
arr.forEach(item => { })
console.timeEnd('forEach~循环');
// forEach~循环: 13.69091796875 ms
console.time('forin~循环');
for (let key in arr) { }
console.timeEnd('forin~循环');
// forin~循环: 141.619140625 ms
console.time('for of~循环');
for (let val of arr) { }
console.timeEnd('for of~循环');
// for of~循环: 24.56787109375 ms
可以在控制台尝试一下,可以看到各种循环的性能对比,很明显,for while 循环性能最好
简单实现forEach循环
Array.prototype.forEach = function forEach(callback) {
// 提前定义 index,arrLength避免每次循环都重新创建index 重新获取length 造成没必要的性能浪
let index = 0,
arrLength = this.length,
self = this; // this指向forEach的调用者
if (typeof callback !== "function") new Error('callback is not function')
for (; index < arrLength; index++) {
callback(self[index], index, self)
}
}
let arr1 = [1, 2, 3]
arr1.forEach((item, index, data) => {
console.log(item, index, data)
})
在这里我们可以分析,forEach内部对循环做了封装处理以及判断消耗了一些性能,但是在实际项目中推荐使用forEach,可以提高开发效率,减少一些不必要的麻烦。
for in 循环原理
for...in 语句以任意顺序迭代一个对象的除[Symbol]以外的[可枚举]属性,包括继承的可枚举属性。
迭代当前对象中所有可枚举的属性[私有属性大部分是可枚举的,公有属性{出现在所属类的原型上的}也有部分是可枚举的],查找机制上一定会搞到原型链上去。
// 看下这个例子就明白了
Object.prototype.aaa = {
a:'1'
}
let arr2 = [1,2,3,4,5];
for (var key in arr2) {
// 在此处会将 aaa 属性也遍历到
console.log(key);
}
// 所以在实际中大多数不会使用for in
// 使用Object.keys() Reflect.ownKeys() 去遍历会更方便
for of 循环原理
- for of 循环的原理是按照迭代器规范遍历的
- iterator迭代器 是一种规范
- 部分数据结构实现了迭代器规范
- Symbol.iterator
- 数组/部分类素组/Set/Map...
- 对象没有实现
let arr3 = [2, 3, 5]
arr3[Symbol.iterator] = function () {
let self = this,
i = 0
return {
// iterator通过next下一步的调用获取每个可枚举的值
// next函数返回一个对象,done表示当前是否已经循环结束,value表示返回值
next() {
if (i > self.length - 1) return {
done: true,
value: undefined
}
return {
done: false,
value: self[i++]
}
}
}
}
for (var val of arr3) { console.log(val) }