> 文章列表 > JS中三类循环对比及性能分析

JS中三类循环对比及性能分析

JS中三类循环对比及性能分析

JS中三类循环对比及性能分析

for循环与while

当我们使用let声明变量的时候 我们可以看到for循环的性能要好一些

let arr = new Array(9999999).fill(0);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");

JS中三类循环对比及性能分析
但是如果使用var来声明 会发现for循环与while循环差不多

let arr = new Array(9999999).fill(0);console.time("FOR");
for (var i = 0; i < arr.length; i++) {}
console.timeEnd("FOR");
console.time("WHILE");
var i = 0;
while (i < arr.length) {i++;
}
console.timeEnd("WHILE");

JS中三类循环对比及性能分析
总结:for循环时自己控制循环过程
基于var声明的时候 for和while性能差不多 (不确定循环次数的情况下使用while)
基于let声明的时候 for循环性能更好 (原理:没有创造全局不释放的变量)

for与forEach

forEach比for的性能差一些

let arr = new Array(9999999).fill(0);console.time("FOR");
for (var i = 0; i < arr.length; i++) {}
console.timeEnd("FOR");
console.time("WHILE");
var i = 0;
while (i < arr.length) {i++;
}
console.timeEnd("WHILE");
console.time("FOREACH");
arr.forEach(function () {});
console.timeEnd("FOREACH");

JS中三类循环对比及性能分析

实现forEach

Array.prototype.forEach = function forEach(callback,context){//this -> arrlet self = this,i = 0,len = self.length;context = context === null ? window : contextfor(; i < len ; i++){typeof callback === 'function' ? callback.call(context,self[i],i) : null}
}

for in 循环

for in 的性能很差:用来迭代当前对象中所有可枚举的属性的 (私有属性大部分是可枚举的 注意length不可枚举,公有属性【出现在所属类的原型上的】也有部分是可枚举的) 查找机制上一定会搞到原型链上去

let arr = new Array(9999999).fill(0);console.time("FOR");
for (var i = 0; i < arr.length; i++) {}
console.timeEnd("FOR");console.time("WHILE");
var i = 0;
while (i < arr.length) {i++;
}
console.timeEnd("WHILE");console.time("FOREACH");
arr.forEach(function () {});
console.timeEnd("FOREACH");console.time("FORIN");
for (let key in arr) {
}
console.timeEnd("FORIN");

JS中三类循环对比及性能分析
for in的问题

//问题一:遍历顺序以数字属性优先 从小到大
//问题二:无法遍历Symbol属性
//问题三:可以遍历到共有中可枚举的属性
Object.prototype.fn = function () {};
let obj = {name: "gh",age: 24,[Symbol("AA")]: 100,0: 100,1: 200,
};for (let key in obj) {console.log(key);
}

JS中三类循环对比及性能分析
解决方法一 使用hasOwnProperty

Object.prototype.fn = function () {};
let obj = {name: "gh",age: 24,[Symbol("AA")]: 100,0: 100,1: 200,
};for (let key in obj) {if (!obj.hasOwnProperty(key)) {break;}console.log(key);
}

解决方法二 使用Object.keys() Object.
JS中三类循环对比及性能分析

Object.prototype.fn = function () {};
let obj = {name: "gh",age: 24,[Symbol("AA")]: 100,0: 100,1: 200,
};let keys = Object.keys(obj);
if (typeof Symbol !== "undefined") keys = keys.concat(Object.getOwnPropertySymbols(obj));
keys.forEach((key) => {console.log("属性名: ", key);console.log("属性值: ", obj[key]);
});

JS中三类循环对比及性能分析

for of

for of比forEach差一点

let arr = new Array(9999999).fill(0);console.time("FOR");
for (var i = 0; i < arr.length; i++) {}
console.timeEnd("FOR");console.time("WHILE");
var i = 0;
while (i < arr.length) {i++;
}
console.timeEnd("WHILE");console.time("FOREACH");
arr.forEach(function () {});
console.timeEnd("FOREACH");console.time("FORIN");
for (let key in arr) {
}
console.timeEnd("FORIN");console.time("FOROF");
for (let key of arr) {
}
console.timeEnd("FOROF");

JS中三类循环对比及性能分析
部分数据结构实现了迭代器规范
所有拥有Symbol.iterator就实现了迭代器规范
for of循环的原理:按照迭代器规范遍历的

数组、部分类数组(argument实现了)、set、map【对象没有实现】

  1. let itor = arrSymbol.iterator
  2. itor.next()

实现迭代

arr = [10, 20, 30];
arr[Symbol.iterator] = function () {let self = this,index = 0;return {//必须具备next方法 每执行一次next方法 拿到结构中的每一项的值//done:false 没有完成 value:每一项的值//如果当前的索引大于 数组最大索引就结束next() {if (index > self.length - 1) {return { done: true, value: undefined };}return { done: false, value: self[index++] };},};
};

让对象具备迭代属性

//类数组对象 【默认不具备迭代器规范】
let obj = {0: 100,1: 200,2: 300,length: 3,
};obj[Symbol.iterator] = Array.prototype[Symbol.iterator];for (let val of obj) {console.log(val);
}