Array循环for、for in、for of、forEach各间优劣
JavaScript中有多种循环Array的方式,你是否常常分不清他们的细微差别,和适用场景。本文将详细梳理各间的优缺点,整理成表以便对比。
循环 | 可访问element | 可访问index | 可迭代property | 支持中断 | 支持await | 支持任意位置开始 |
---|---|---|---|---|---|---|
for | √ | √ | × | √ | √ | √ |
for in | √ | × | √ | √ | √ | × |
forEach | √ | √ | × | × | × | × |
for of | √ | √ | × | √ | √ | × |
for (ES1)
这个循环方式历史悠久,从ECMAScript 1就被支持。
const arr = ['a', 'b', 'c'];
arr.prop = 'property value';
for (let index=0; index < arr.length; index++) {
const elem = arr[index];
console.log(index, elem);
}
// Output:
// 0, 'a'
// 1, 'b'
// 2, 'c'
for
循环方式通用,迭代过程可以访问元素和当前元素下标索引,但是语法上略显冗长。
for in (ES1)
for in
的历史同for
一样悠久。
const arr = ['a', 'b', 'c'];
arr.prop = 'property value';
for (const key in arr) {
console.log(key);
}
// Output:
// '0'
// '1'
// '2'
// 'prop'
for in
用来循环数组不是一个合适的选择。
- 迭代的是属性key,不是值
- 由于属性
key
是字符串,迭代出的元素索引是string
,不是number
. - 迭代的是数组实例上所有可枚举的属性key,而不是数组内元素。
如果你想获取一个对象所有的可枚举属性(包含原型链上的),那么 for in
倒是可以胜任,若仅仅是对象自身声明的属性,那 Object.keys
更合适。
forEach (ES5)
鉴于 for
和 for-in
都不特别适合在 Arrays
上循环,因此在ECMAScript 5中引入了辅助方法:Array.prototype.forEach
.
const arr = ['a', 'b', 'c'];
arr.prop = 'property value';
arr.forEach((elem, index) => {
console.log(elem, index);
});
// Output:
// 'a', 0
// 'b', 1
// 'c', 2
这个方法很方便,它让我们可以访问数组元素和数组元素下标,而不需要做太多的事情。箭头函数(在ES6中引入)使该方法在语法上更加优雅。
forEach
主要确定是:
- 循环内部不支持
await
操作。 - 即使找到你想要的元素,也无法中断循环。
要实现中断循环,可以使用同期引入的 Array.prototype.same
方法。some
循环遍历所有 Array
元素,并在其回调返回一个真值时停止。
const arr = ['red', 'green', 'blue'];
arr.some((elem, index) => {
if (index >= 2) {
return true; //结束循环
}
console.log(elem);
// 隐式返回假值 undefined,继续循环
});
// Output:
// 'red'
// 'green'
for of (ES6)
for of
是 ECMAScript 6 新引入的语法。
const arr = ['a', 'b', 'c'];
arr.prop = 'property value';
for (const elem of arr) {
console.log(elem);
}
// Output:
// 'a'
// 'b'
// 'c'
for of
很适合遍历数组:
- 迭代所有数组元素
- 内部支持
await
,甚至是ES2018
中引入的for-await-of
语法 - 可以使用 break 和 continue 跳出循环
for-of
的另一个好处是,我们不仅可以遍历数组,还可以遍历任何可迭代对象(例如map)
const myMap = new Map()
.set(false, 'no')
.set(true, 'yes')
;
for (const [key, value] of myMap) {
console.log(key, value);
}
// Output:
// false, 'no'
// true, 'yes'
遍历 myMap
会生成[key, value]对,对其进行解构方便直接访问。
如果你在循环中需要感知当前元素索引,可以通过 Array
方法 entries
返回可迭代的 [index,value]对。 和map一样的解构直接访问index、value:
const arr = ['chocolate', 'vanilla', 'strawberry'];
for (const [index, value] of arr.entries()) {
console.log(index, value);
}
// Output:
// 0, 'chocolate'
// 1, 'vanilla'
// 2, 'strawberry'
循环体内 await 测试
准备如下代码用于测试循环体内 await
,getFruit
模拟远程服务延迟返回。
const fruits = ["apple", "grape", "pear"];
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const getFruit = (fruit) => {
return sleep(2000).then((v) => fruit);
};
先看 for of
, 元素之间会按预期间隔输出。
(async function(){
console.log('start');
for (fruit of fruits) {
const element = await getFruit(fruit);
console.log(element);
}
console.log('start');
})();
//3个元素 间隔2s输出
"start"
"apple"
"grape"
"pear"
"end"
再看 forEach
, 注意 forEach
调用后直接返回输出 loop end, 间隔2s 后同时输出了后面结果,并没有按预期各个间隔输出。
(async function () {
console.log("foreach loop start ....");
fruits.forEach(async value => {
const element = await getFruit(value);
console.log(element);
});
console.log("foreach loop end ....");
})();
//同时输出
foreach loop start ....
foreach loop end ....
//间隔2s 后同时输出下面3个
apple
grape
pear
Array循环for、for in、for of、forEach各间优劣的更多相关文章
- JavaScript Array -->map()、filter()、reduce()、forEach()函数的使用
题目: 1.得到 3000 到 3500 之内工资的人. 2.增加一个年龄的字段,并且计算其年龄. 3.打印出每个人的所在城市 4.计算所有人的工资的总和. 测试数据: function getDat ...
- 【js jQuery】map集合 循环迭代取值---以及 map、json对象、list、array循环迭代的方法和区别
后台给前台传来一个map @ResponseBody @RequestMapping(value = "getSys") public Map<Long,String> ...
- PHP.34-TP框架商城应用实例-后台10-商品分类-需求分析、创建无限级商品分类,递归
商品管理需求分析 1.实现商品无限级分类管理[类似京东三级分类] 2.添加商品时要指定商品属于一个主分类和多个扩展分类[扩展分类可以是其他主分类] 3.商品列表中可以根据分类搜索商品 a) 搜索一个分 ...
- php的array数组 -------方法foreach循环时候,利用数组里值的引用地址(& )从而改变数组里的值
/* * 把每个数组值后面都加个SQL然后返回数组 * foreach循环时候,直接用引用(&)的方式就能改变之前的数组 */public function array_foreach(){ ...
- JAVA中的for-each循环与迭代
在学习java中的collection时注意到,collection层次的根接口Collection实现了Iterable<T>接口(位于java.lang包中),实现这个接口允许对象成为 ...
- 集合框架遍历方式之——for-each循环
从Java5起,在Java中有了for-each循环,可以用来循环遍历collection和array.Foreach循环允许你在无需保持传统for循环中的索引,或在使用iterator /ListI ...
- ecshop循环foreach,iteration,key,index
转载: 最近刚接触ecshop不久,感觉是非常的强大,做商城网站,整个流程都差不多搞好了,就是支付流程要自己完善完善,不过也有不足,文章功能还不够好. 通过几天的应用,总结出了ec模版中foreach ...
- forEach 方法 (Array) (JavaScript)
为数组中的每个元素执行指定操作. 语法 array1.forEach(callbackfn[, thisArg]) 参数 参数 定义 array1 必选.一个数组对象. callbackfn 必选.最 ...
- php学习笔记:foreach循环访问关联数组里的值
foreach循环可以将数组里的所有值都访问到,下面我们展示下,用foreach循环访问关联数组里的值. 例如: $fruit=array('apple'=>"苹果",'ba ...
随机推荐
- Mysql中的语句优化
1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...
- C++ 入门篇
C++基础入门 1 C++初识 1.1 第一个C++程序 编写一个C++程序总共分为4个步骤 创建项目 创建文件 编写代码 运行程序 1.1.1 创建项目 Visual Studio是我们用来编写 ...
- 在Termux(非root的安卓Linux模拟器)中安装和使用ftp服务器(pure-ftpd)(原创)[简单极致]
Termux是单用户的linux模拟器,所以应用的专属文件夹下面.usr/etc/下面没有passwd和group文件对多用户组配置,只在.usr/bin/下面有passwd二进制应用可以改变当前用户 ...
- vim_command
vi 打开vi空白面板 vi filename 以编辑模式打开文件.如果参数为已有文件,在vi中打开:如果参数为新文件名,在vi退出时提示用户保存编辑内容 vi -R filename 以只读模式打开 ...
- 如何优雅的传递 stl 容器作为函数参数来实现元素插入和遍历?
问题背景 开始正文之前,做一些背景铺垫,方便读者了解我的工程需求.我的项目是一个客户端消息分发中心,在连接上消息后台后,后台会不定时的给我推送一些消息,我再将它们转发给本机的其它桌面产品去做显示.后台 ...
- 详解线程池的作用及Java中如何使用线程池
服务端应用程序(如数据库和 Web 服务器)需要处理来自客户端的高并发.耗时较短的请求任务,所以频繁的创建处理这些请求的所需要的线程就是一个非常消耗资源的操作.常规的方法是针对一个新的请求创建一个新线 ...
- 【JDBC核心】DAO 相关
DAO 相关 概念 DAO:Data Access Object 访问数据信息的类和接口,包括了对数据的 CRUD(Create.Retrival.Update.Delete),而不包含任何业务相关的 ...
- IntelliJ IDEA启动界面的秘密:当编程遇到艺术
细心的同学会发现Intellij IDEA每次发版本的时候都会有不同的启动界面背景,都很比较抽象的艺术图像. JetBrains的其它产品也有自己独特的设计. 但是这背后是怎么实现的.有什么寓意却很少 ...
- docker 容器和镜像的常用命令
镜像 docker rmi 镜像id -f # 删除指定镜像 docker rmi 镜像id 镜像id -f # 删除多个镜像 docker rmi -f $(docker images -aq) # ...
- 【Linux】ssh反映特别慢,但是网络没有问题的时怎么办
用crt连接服务器的时候,感觉很久才有反映,大约持续2秒以上,这种情况下,是解析的问题 这里有一个方法可以优化ssh cd /etc/ssh/ cp sshd_config sshd_config.b ...