forEach

  数组实例的遍历方法

const arr=['red', 'green', 'blue'];
arr.forEach(function(element, index) {
console.log(element);// red green blue
console.log(index);// 0 1 2
});

  forEach这种写法的问题是,无法中途跳出forEach循环,break命令或return命令都不能奏效。

for...in

  JavaScript原有的循环,只能获得对象的键名,不能直接获取键值。

var arr = ['a', 'b', 'c', 'd', 'e'];
for(let i in arr) {
console.log(i);//0 1 2 3 4
}
for(let index in arr) {
console.log(arr[index]);// a b c d e
}
let es6 = {
edition: 6,
committee: "TC-39",
standard: "ECMA-262"
};
for(let e in es6) {
console.log(e);
}
//edition
//committee
//standard

  for...in循环有几个缺点:

    数组键名是数字,但是for...in循环是以字符串作为键名"0","1","2"等

    for...in循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。

    某些情况下,for...in循环会以任意顺序遍历键名。

  总之,for...in循环主要是为遍历对象为设计的,不适用于遍历数组。

for...of

  ES6借鉴C++、Java、C#和Python语言,引入了for...of循环,作为遍历所有数据结构的统一的方法。一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。for...of循环可以使用的范围包括数组、Set和Map结构、某些类似数组的对象(比如arguments对象、DOM NodeList对象)、Generator对象以及字符串。

  数组原生具有iterator接口(即默认部署了Symbol.iterator属性),for...of循环本质上就是调用这个接口产生的遍历器,允许遍历获得键值

var arr = ['a', 'b', 'c', 'd', 'e'];
for(let i of arr) {
console.log(i);//a b c d e
}

  for...of循环可以代替数组实例的forEach方法

  for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性;这一点与for...in也不一样。

let arr = [1,3,5];
arr.foo = 'hello';
for(let i in arr) {
console.log(i);//'1', '3', '5', 'foo'
} for(let i of arr) {
console.log(i);//'1', '3', '5'
}

  Set和Map结构也原生具有Iterator接口,可以直接使用for...of循环

var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for(var e of engines) {
console.log(e);
}
//Gecko
//Trident
//Webkit
var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for(var [name, value] of es6) {
console.log(name+ ":" + value);
}
//edition: 6
//committee: TC39
//standard: ECMA-262

  Set和Map遍历的顺序是按照各个成员被添加进数据结构的先后顺序。其次,Set结构遍历,返回的是一个值。Map结构遍历返回的是一个数组,该数组的两个成员分别为当前Map成员的键名和键值。

  for...of循环,获得数组的索引,可以借助数组实例的entries方法和keys方法。

let arr = ["a", "b", "c"];
for(let pair of arr.entries()) {
console.log(pair);
}
//[0, 'a']
//[1, 'b']
//[2, 'c']

  for...of遍历类似数组的对象(String、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'

  对字符串来说,for...of循环还能够正确识别32位UTF-16字符

for (let x of 'a\uD83D\uDC0A) {
console.log(x);
}
//'a'
//'\uD83D\uDC0A'

  并不是所有类似数组的对象都具有Iterator接口,一个方法是用Array.from方法将其转换为数组

let  arrayLike = [length: 2, 0: 'a', 1: 'b'];
for(let x of array.from(arrayLike)) {
console.log(x);
}

  对于普通的对象,for...of结构不能直接使用,必须部署Iterator接口后才能使用。一种解决方法是将对象的键名生成一个数组,然后遍历这个数组:

for(let key of Object.keys(someObject)) {
console.log(key + ":" + someObject[key]);
}

  另一个方法是使用Generator函数

function* entries(obj) {
for(let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for(let [key, value] of entries(obj)) {
console.log(key, '->', value);
}
//a -> 1
//b -> 2
//c -> 3

  for...of相对其它遍历方法,有以下优点:

    有着同for...in一样简洁的语法,但是没有for...in那些缺点;

    不同于forEach方法,它可以与break、continue和return配合使用

    提供了遍历所有数据结构的统一操作接口

for(var n of fibonacci) {
if(n>1000)
break;
console.log(n);
}

参考:

Iterator和for...of

最新文章

  1. android4.4源码下载简介
  2. NTDLL未文档化函数RtlGetNtVersionNumbers获取操作系统版本
  3. 《UML大战需求分析》阅读笔记5
  4. 【真的是随笔】如何利用htaccess把网站流量引到一个页面上(站点维护页效果)
  5. [转]Hibernate与Jpa的关系,终于弄懂
  6. win10蓝屏问题,关于驱动kisSaasUrlRedirectKnl64.sys 的
  7. 原生js实现中文时钟
  8. POJ_1742_Coins_(动态规划,多重部分和)
  9. 关于crontab笔记
  10. Confluence 持续集成平台部署记录
  11. 2017 Multi-University Training Contest - Team 1 1011&&HDU 6043 KazaQ's Socks【规律题,数学,水】
  12. 洛谷P4219 [BJOI2014]大融合(LCT,Splay)
  13. 记一次Java调优案例分析
  14. webForm TO MVC
  15. Hibernate学习笔记3.3(Hibernate组建映射2)
  16. ubuntu14配置opencv3.4.1(转)
  17. C++调用IDL程序的做法(三)
  18. hdoj2191 珍惜现在,感恩生活(01背包 || 多重背包)
  19. js:{}与new Object()的区别是什么
  20. BCD码转换为十进制或者十进制转为BCD码

热门文章

  1. git 基础教程
  2. pat1044. Shopping in Mars (25)
  3. CF1096C Polygon for the Angle
  4. 认识less和webstrom的less配置
  5. jQuery(四)(DOM一)
  6. Linux 两组信号对比
  7. Form上传编译
  8. Linq to Sql 左连接 , 取右表可能为 null的 int类型字段
  9. Odoo (OpenERP/TinyERP)-10.0 (Debian 8)
  10. springboot/springmvc转换器