JS中的循环性能比较情况

139 阅读2分钟
  • 在js中 循环有很多种方式,比如: for 、forIn 、forOf、forEach、while,还有数组类循环map、filter、reduce等等。不同的循环在不同的情况下,性能和使用方式是不同的。

for & while & forEach

  • for循环:可以控制自己的循环过程

  • while循环:一般不清楚具体的循环过程,不清楚会循环多少次,只是满足了某个条件进行循环,否则终止。

  • forEach 将循环进行了封装,依托函数式编程,更关注结果,而不是去注重过程。

  • 在基于VAR 声明的情况下,for 和 while 性能是差不多的 [在不确定次数的情况下,选择while]

  • 在基于LET 声明的情况下,for循环性能更高 [没有创造出全局不释放的变量]

  • forEach 单纯从性能来说,其实不如 for/while 的。但是由于注重结果,而非过程,所以项目里用的多的还是这个forEach.

  • 如果循环少,不考虑性能,而且我们仅仅关注结果的情况下,可以直接使用 forEach就好

  • 函数式和命令式

    • 命令式,注重些操作过程,过程中我们可以进行打断等操作,比如使用break / continue。
    • 函数式,更注重结果,我不关注中间过程如何,给我最后的结果就好。而且这种函数式中间也挺难打断终止执行的。
let arr = new Array(99999999).fill("");
​
console.time('FOR~~');
for(let i =0; i< arr.length; i++) {}
console.timeEnd('FOR~~');
​
console.time('WHILE~~');
let i=0;
while(i<arr.length) { i++ }
console.timeEnd('WHILE~~');
​
console.time('EACH~~');
arr.foeEach(item => {});
console.timeEnd('EACH~~');

重写forEach方法

Array.prototype.forEach = function forEach(cb, context) {
    let _this = this; // this谁调用就是谁
    let i = 0,
        len = _this.length;
    context = context == null? window: context; // 第二个参数是改变上下文指向,默认为window
    for(; i<len; i++) {
        typeof cb === "function"? cb.call(context, len[i], i): null;
    }
    
}

forIn

  • forIn 循环的性能特别的差

  • 因为会 迭代当前对象中所有可枚举的属性的,包括私有和公有的。 【私有属性大部分是可枚举的,公有属性(出现在所属类的原型上)也有部分是可枚举的】。查找机制上一定会跑到原型链上去。

  • 存在的问题:

    1. 遍历的顺序,以数字为主
    2. 无法遍历 Symbol 属性
    3. 可以遍历到 原型上公有可枚举的属性
Obect.prototype.fn = function() {};
let obj = {
    name: 'wj',
    age: 31,
    [Symbol]: 'bj',
    0: 'hh',
    1: 'dd'
}
​
for(let key in obj) {
    if(obj.hasOwnPrototype(key)) break; // 优化点: 去除原型上的属性
    console.log(key);
}

forOf

  • 性能比 forIn 要强一些。
  • forOf 不能进行对象循环
  • 可以在数组、Set、Map... 等具有 iterator 接口的数据结构中使用
arr[Symbol.iterator] = function() {
    let _this = this, // 指代循环的元素
        index = 0;
    return {
        next() {
            if(index > _this.length - 1) {
                return {
                    value: undefined,
                    done: true,
                }
            }
            return {
                value: _this[index++],
                done: false
            }
        }
    }
}
​
for(let val of arr) {
    console.log(val);
}
let obj = {
    0: 'wj',
    1: 'lft',
    2: 'wyx',
    length: 3,
    [Symbol.iterator]: ([])[Symbol.iterator]
}
​
for(let name of obj) {
    console.log(name);
}
​