JS中for...in循环陷阱及遍历数组的方式对比
JavaScript中有很多遍历数组的方式,比较常见的是for(var i=0;i<arr.length;i++){},以及for...in...循环等,这些遍历都有各自的优缺点,下面来看看各种JS的遍历对比:
1.for...in...
1).index索引为字符串型数字,不能直接进行几何运算。
2).遍历顺序有可能不是按照实际数组的内部顺序。
3).使用for in会遍历数组所有的可枚举属性,包括原型。例如上栗的原型方法method和name属性。
Array.prototype.myfun=function(){
alert('myfun');
}
var arr = [0,1,2,3];
for(var i in arr){
console.log(arr[i]);
}
console.log(Array.prototype)
运行结果:

上面的例子很好的反映了for...in...循环的缺点,原本只想循环取出该数组的数据,但是由于之前给数组添加了原型函数,导致循环的结果多了一个函数。这种场景我在使用lodop打印控件写打印功能时遇到过,打印的内容我用for...in...循环打印了,结果打印的结果莫名其妙多了一串代码,排查了很久才发现原来是lodop.js将Array数组的原型添加了方法,导致循环的时候将该方法也遍历到了,所以for...in...循环最好使用在遍历对象上,不要用来遍历数组。
2.普通for循环
let arr = [1,2,3,4,5];
for (var index = 0; index < arr.length; index++) {
console.log(arr[index]);
}
这是最原始的写法,也是应用比较多的循环方式,但写法较为麻烦,性能有优化空间。
3.优化for循环
var arr = [0,1,2,3];
for(j=0,len=arr.length;j<len;j++){
console.log(arr[j]);
}
使用临时变量,将长度缓存起来,避免重复获取数组长度,当数组较大时优化效果才会比较明显。这种方法基本上是所有循环遍历方法中性能最高的一种,所以推荐使用这种循环。
4.forEach循环
let arr = [1,2,3,4,5];
arr.forEach((element,index) => {
console.log(element);
});
forEach循环是数组自带的方法,这种方式循环十分方便,不需要获取数组长度即可循环,但是有一个问题,在循环的中途无法跳出forEach循环,break命令或return命令都不能奏效,也就是说一循环必然会执行完毕,不能灵活运用于多种情况。
5.for...of...循环
for…of是ES6新增的遍历方式,它提供了统一的遍历机制。所有实现了[Symbol.iterator]接口的对象都可以被遍历。for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、Generator 对象,以及字符串。
优点:
- 有着同
for...in一样的简洁语法,但是没有for...in那些缺点 - 不同用于
forEach方法,它可以与break、continue和return配合使用 - 提供了遍历所有数据结构的统一操作接口
下面是一个使用break语句,跳出for...of循环的例子。
for (var n of arr) {
if (n > 2) break;console.log(n);
}
上面的例子,会输出斐波纳契数列小于等于2的项。如果当前项大于2,就会使用break语句跳出for...of循环。
for...of获取索引
entries返回一个遍历器对象,用来遍历[键名, 键值]组成的数组。对于数组,键名就是索引值;对于 Set,键名与键值相同。Map 结构的 Iterator 接口,默认就是调用entries方法。keys返回一个遍历器对象,用来遍历所有的键名。values返回一个遍历器对象,用来遍历所有的键值。
let arr = ['a', 'b', 'c'];
for (let pair of arr.entries) {
console.log(pair);
} // [0, 'a'] // [1, 'b'] // [2, 'c']
类似数组的对象
类似数组的对象包括好几类。下面是for...of循环用于字符串、DOM NodeList 对象、arguments对象的例子。
// 字符串
let str = "hello";
for (let s of str) {
console.log(s); // h e l l o
} // DOM NodeList对象
let paras = document.querySelectorAll("p");
for (let p of paras) {
p.classList.add("test");
} // arguments对象
function printArgs {
for (let x of arguments) {
console.log(x);
}
}
printArgs('a', 'b'); // 'a' // 'b'
并不是所有类似数组的对象都具有 Iterator 接口,一个简便的解决方法,就是使用Array.from方法将其转为数组。
let arrayLike = {
length: 2,
0: 'a',
1: 'b'
};
// 报错
for (let x of arrayLike) {
console.log(x);
}
// 正确
for (let x of Array.from(arrayLike)) {
console.log(x); // 'a' // 'b'
}
普通的对象
对于普通的对象,for...of结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。
let es6 = {
edition: 6,
committee: "TC39",
standard: "ECMA-262"
};
for (let e in es6) {
console.log(e);
} // edition // committee // standard
for (let e of es6) {
console.log(e);
} // TypeError: es6 is not iterable
解决方法是,使用Object.keys方法将对象的键名生成一个数组,然后遍历这个数组。
let es6 = {
edition: 6,
committee: "TC39",
standard: "ECMA-262"
};
for (var key of Object.keys(es6)) {
console.log(key + ': ' + es6[key]);
}
JS中for...in循环陷阱及遍历数组的方式对比的更多相关文章
- js事件、Js中的for循环和事件的关系、this
一.js事件 1.事件 用户在网页中所触发的行为 鼠标滑动种类很多,键盘.表单特列: 点击:onclick 鼠标进入:onmouseenter 鼠标离开:onmouseleave 鼠标悬浮:onmo ...
- php中的for循环和js中的for循环
php中的for循环 循环100个0 for ($i=0;$i<=100;$i++){ $pnums.='0'.","; } js中的for循环,循环31个相同的数.循环日期 ...
- 原生js使用forEach()与jquery使用each遍历数组,return false 的区别
原生js使用forEach()与jquery使用each()遍历数组,return false 的区别: 1.使用each()遍历数组a,如下: var a=[20,21,22,23,24]; $.e ...
- JS中如何判断对象是对象还是数组
JS中如何判断对象是对象还是数组 一.总结 一句话总结:typeof Array.isArray === "function",Array.isArray(value)和Objec ...
- js中构造函数的原型添加成员的两种方式
首先,js中给原型对象添加属性和方法. 方式一:对象的动态特效 给原型对象添加成员 语法:构造函数.prototype.方法名=function (){ } 方式二:替换原型对象(不是覆盖,而是替换, ...
- js中的for-of循环遍历数组
遍历数组要怎么做,可能你首先想到的会是for循环,当然for循环在JavaScript 刚萌生的时候就出现了,想到它也是理所当然的 var a=[[1,2],[3,4],5] for(var i=0; ...
- js 中常用的循环
参考文章: 1.js几种数组遍历方式以及性能分析对比 2.javaScript遍历对象.数组总结 首先是数组中可以使用的 1.for 循环 for (let i = 0; i < xxx.len ...
- JavaScript中for..in循环陷阱介绍
for...in循环中的循环计数器是字符串,而不是数字它包含当前属性的名称或当前数组元素的索引,下面有个不错的示例大家可以参考下 大家都知道在JavaScript中提供了两种方式迭代对象: (1) ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
[摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...
随机推荐
- 驱动领域DDD的微服务设计和开发实战
你是否还在为微服务应该拆多小而争论不休?到底如何才能设计出收放自如的微服务?怎样才能保证业务领域模型与代码模型的一致性?或许本文能帮你找到答案. 本文是基于 DDD 的微服务设计和开发实战篇,通过借鉴 ...
- 【python测试开发栈】帮你总结python random模块高频使用方法
随机数据在平时写python脚本时会经常被用到,比如随机生成0和1来控制逻辑.或者从列表中随机选择一个元素(其实抽奖程序也类似,就是从公司所有人中随机选择中奖用户)等等.这篇文章,就帮大家整理在pyt ...
- 为什么使用kotlin可以节省开发时间
前言:.kotlin是一门语言,光靠一篇文章要入门不太现实,所以这篇文章重点讲的是kotlin相对于java的一些特性和这些特性带来的好处. 一.简单介绍 Kotlin 是一种在 Java 虚拟机上运 ...
- cocos2dx Quaternion 四元数(1/2)
这篇文章只是我学完四元数之后的一些理解,其实是对别人理解的理解,有些地方我理解但是没有写下来,如果真的想深入的学习四元数,建议从学习复数开始. 这个知识点需要几何想象的天赋和学习的耐心,缺一不可,慢慢 ...
- MySQL 核心三剑客 —— 索引、锁、事务
一.常见存储引擎 1.1 InnoDB InnoDB 是 MySQL 5.5 之后默认的存储引擎,它具有高可靠.高性能的特点,主要具备以下优势: DML 操作完全遵循 ACID 模型,支持事务,支持崩 ...
- 超详细Node安装教程
今天周末休息,我制定了我的2020年度规划,其中包含编写50篇养成写博文的习惯.算下来平均每周一篇,感觉也不是很难,但我的写作能力不是很好,争取一次比一次好!希望自己能够坚持下去.2020为自己而活, ...
- 1082 射击比赛 (20 分)C语言
本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军:谁差得最远,谁就是菜鸟.本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟.我们假设靶心在原点(0,0). 输入 ...
- js滑动导航栏点击后居中效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 一条SQL注入引出的惊天大案
前情回顾: WAF公司拦截到一个神秘的HTTP数据包,在这个包的表单字段中发现了SQL语句.目标指向80端口,而这正是nginx公司的地盘.详情参见:一个HTTP数据包的奇幻之旅 虚拟机的世界 一个安 ...
- 10_时间戳timeStamp 和 时间 time 转换, 根据时间节点倒计时
1: 时间戳 timeStamp 获取的几种方法及其优劣, 第一种只能精确到秒, 故不推荐使用, 最最常用的也是最官方的是第三种, 通过原型方法进行调用获取精确到毫秒数 : var timestamp ...