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中三类循环对比及性能分析_第1张图片
但是如果使用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中三类循环对比及性能分析_第2张图片
总结: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中三类循环对比及性能分析_第3张图片

实现forEach

Array.prototype.forEach = function forEach(callback,context){
	//this -> arr
	let self = this,
	i = 0,
	len = self.length;
	context = context === null ? window : context
	for(; 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中三类循环对比及性能分析_第4张图片
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中三类循环对比及性能分析_第5张图片
解决方法一 使用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中三类循环对比及性能分析_第6张图片

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中三类循环对比及性能分析_第7张图片

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中三类循环对比及性能分析_第8张图片
部分数据结构实现了迭代器规范
所有拥有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);
}

你可能感兴趣的:(js,javascript,前端,开发语言)