js几种循环总结

70 阅读2分钟

对比性能

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) }