在开发过程中经常需要循环遍历数组或者对象,js也为我们提供了不少方法供使用,其中就有三兄弟forEach、for...in、for...of,这三个方法应该是使用频率最高的,但很多人却一值傻傻分不清,经常该混淆了它们的功能和注意点。就在今天,我来给它们一个大区分(*・ω< )。

forEach

forEach() 方法对数组的每个元素执行一次提供的函数。

从ES5开始,Javascript内置了forEach方法,用来遍历数组 。

var arr = ['a', 'b', 'c', 'd', 'e'];

arr.forEach(function(item) {
console.log(item); // a,b,c,d,e
});

!注意:forEach方法没办法使用 break 语句跳出循环,或者使用return从函数体内返回。

for...in

for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。

语法:

for (variable in object) {...}

variable 在每次迭代时,将不同的属性名分配给变量。

object 被迭代枚举其属性的对象。

// 例子一
let obj = {a: '1', b: '2', c: '3', d: '4'};
for (let o in obj) {
console.log(o) // 遍历的实际上是对象的属性名称 a,b,c,d
console.log(obj[o]) // 这个才是属性对应的值1,2,3,4
} // 例子二
Object.prototype.objName = 'objName ';
var obj = {a: '1', b: '2', c: '3', d: '4'};
for (let o in obj) {
console.log(o) // a,b,c,d,objName
}

for...in 循环只遍历可枚举属性。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototype和String.prototype的不可枚举属性,例如 String 的 indexOf()  方法或 Object的toString()方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。

! 注意:建议不使用for...in去迭代一个Array。因为设计之初,是给普通以字符串的值为key的对象使用的,而非数组。

数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。使用不能保证for...in将以任何特定的顺序返回索引。因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行for循环(或者使用 Array.prototype.forEach() 或 for...of 循环)。

对于for...in的循环,可以由break,throw终止。

var obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o in obj) {
if(o=='c'){
break;
}
console.log(o);
} // 输出: a,b

for...of

for...of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。

语法:

for (variable of iterable) {
//statements
}

variable 在每次迭代中,将不同属性的值分配给变量。

iterable 被迭代枚举其属性的对象。

迭代数组Array

let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value);
}
//
//
//

迭代字符串String

let iterable = "boo";
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"

迭代Map

let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);

for (let entry of iterable) {
console.log(entry);
}
// ["a", 1]
// ["b", 2]
// ["c", 3] for (let [key, value] of iterable) {
console.log(value);
}
//
//
//

迭代Set

let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
console.log(value);
}
//
//
//

对于for...of的循环,可以由breakthrow 或return终止。在这些情况下,迭代器关闭

function* foo(){
yield 1;
yield 2;
yield 3;
}; for (let o of foo()) {
console.log(o);
break; // closes iterator, triggers return
}

for...of与for...in的区别

无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。

for...in 语句以原始插入顺序迭代对象的可枚举属性。

for...of 语句遍历可迭代对象定义要迭代的数据。

以下示例显示了与Array一起使用时,for...of循环和for...in循环之间的区别。

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {}; // 每个对象将继承objCustom属性,并且作为Array的每个对象将继承arrCustom属性,
// 因为将这些属性添加到Object.prototype和Array.prototype。
// 由于继承和原型链,对象iterable继承属性objCustom和arrCustom。
let iterable = [3, 5, 7];
iterable.foo = 'hello world'; // 此循环仅以原始插入顺序记录iterable对象的可枚举属性。
// 它不记录数组元素3, 5, 7 或hello,因为这些不是枚举属性。
// 但是它记录了数组索引以及arrCustom和objCustom。
// 前面说了,不建议使用for...in迭代数组,这里是纯粹举例才这样写,请勿模仿
for (let i in iterable) {
console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
} // 这个循环类似于第一个,但是它使用hasOwnProperty() 来检查,
// 如果找到的枚举属性是对象自己的(不是继承的)。如果是,该属性被记录。
// 记录的属性是0, 1, 2和foo,因为它们是自身的属性(不是继承的)。
// 属性arrCustom和objCustom不会被记录,因为它们是继承的。
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // 0, 1, 2, "foo"
}
} // 该循环迭代并记录iterable作为可迭代对象定义的迭代值,这些是数组元素 3, 5, 7,而不是任何对象的属性。
for (let i of iterable) {
console.log(i); // 3, 5, 7
}

在上面可以粗略看到,for...in循环的是对象的键(key),而for...of则是对象的值。

除此之外,for...of 不能循环非iterable对象。

let newObj = {a: '1', b: '2', c: '3', d: '4'};
for (let o of newObj) {
console.log(o); // Uncaught TypeError: newObj is not iterable
}

实例解析forEach、for...in与for...of的更多相关文章

  1. JavaWeb实现文件上传下载功能实例解析

    转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...

  2. JavaWeb实现文件上传下载功能实例解析 (好用)

    转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...

  3. exec函数族实例解析

    exec函数族实例解析 fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的 ...

  4. [Reprint] C++函数模板与类模板实例解析

    这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下   本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...

  5. [Reprint]C++普通函数指针与成员函数指针实例解析

    这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下   C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...

  6. Android实例-Delphi开发蓝牙官方实例解析(XE10+小米2+小米5)

    相关资料:1.http://blog.csdn.net/laorenshen/article/details/411498032.http://www.cnblogs.com/findumars/p/ ...

  7. Android开发之IPC进程间通信-AIDL介绍及实例解析

    一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用 ...

  8. easyUI:ComboTree and comselector使用实例解析

    ComboTree 使用场景:故名思意,ComboTree是combox和Tree的结合体,在需要通过选择得到某一个node值的时候触发. 栗子: 定义: 使用标签创建树形下拉框. Comselect ...

  9. Maven--多模块依赖实例解析(五)

    <Maven--搭建开发环境(一)> <Maven--构建企业级仓库(二)> <Maven—几个需要补充的问题(三)> <Maven—生命周期和插件(四)&g ...

随机推荐

  1. windows 自动贴边

    设置windows 自动贴边(窗口拖到显示器边框就自动适应屏幕): https://jingyan.baidu.com/article/d2b1d1029d17b95c7e37d4f0.html 资源 ...

  2. Python基础知识:测试代码

    1.Python标准库中的模块unittest提供了代码测试工具. 单元测试用于核实函数的某个方面没有问题: 测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求. 通俗的理解 ...

  3. Beta冲刺(1/5)(麻瓜制造者)

    今天小组进行了第一次冲刺,虽然新组员还没有确定. 今日完成任务 邓弘立:修改登录代码 李佳铭: 用户收藏UI代码编写 江郑: 进行了后台管理员界面ui的设计和环境的搭建 刘双玉:后台github仓库建 ...

  4. oracle中nvarchar2字符集不匹配

    oracle当多表union时遇到nvarchar2类型时报错 字符集不匹配对使用nvarchar的地方,加上 to_char( nvarchar 的变量或字段 ) 如:select to_char( ...

  5. C#深度学习の----深拷贝与浅拷贝

    本人在进行编程的时候遇到一个问题,要对一个绑定的依赖属性进行赋值,改变属性中的某一部分,绑定的目标上的所有值都发生了变化,着并不是我想要的,由此引出深浅拷贝的问题.(请加群交流:435226676) ...

  6. Django之知识总结

    1. 课程介绍 - 数据类型 - 函数 - 面向对象三大特性:继承,封装,多态 - socket:本质传输字节:所有网络通信都基于socket - 数据库设计:单表.FK.M2M (自己作业:自己领域 ...

  7. python五十六课——正则表达式(常用函数之findall)

    4).函数:findall(regex,string,[flags=0]): 参数: 和match.search一样理解 功能: 将所有匹配成功的子数据(子串),以列表的形式返回: 如果一个都没有匹配 ...

  8. maven 打包生成doc和源码插件

    <!--配置生成Javadoc包--> <plugin> <groupId>org.apache.maven.plugins</groupId> < ...

  9. 【转】一个域名是用哪里的DNS来解析的,电脑怎么知道找哪一个DNS呢? 我注册域名的时候会在服务商那里配置DNS解析,一般需要24小时后才能访问,我想知道,解析后的这个数据是不是会同步到世界上所有的DNS服务器呢!如果不是,当我访问我的这个域名的时候,电脑怎么知道去找到我注册的这一家的DNS服务器呢,谁告诉他的呢?

    看看DNS一些基础知识,你就了解了.1.DNS就是域名服务器,他的任务就是确定域名的解析,比如A记录MX记录等等. 2.任何域名都至少有一个DNS,一般是2个.为什么要2个以上呢?因为DNS可以轮回处 ...

  10. Arduino IDE for ESP8266 (0) 官方API

    http://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html 0 简单的连接到WIFI #include <ES ...