「译」forEach循环中你不知道的3件事

前言

本文925字,阅读大约需要7分钟。

总括: forEach循环中你不知道的3件事。

自弃者扶不起,自强者击不倒。

正文

你觉得你真的学会用forEach了么?

这是我之前对forEach循环的理解:就是一个普通语义化之后的for循环,可以被break,continue,return

这篇文章将向你展示forEach中你可能不了解的3件事。

1. return不会停止循环

你觉得下面的代码在打印12之后会停止么?

array = [1, 2, 3, 4];
array.forEach(function (element) {
  console.log(element);

  if (element === 2)
    return;

});
// Output: 1 2 3 4

答案是不会,上述代码会正常打印1,2,3,4。如果你有Java背景,你也许会很诧异,这怎么可能呢?

原因是我们在forEach函数中传了一个回调函数,该回调函数的行为和普通函数一样,我们return操作其实就是普通函数中return。所以并不符合我们预期将forEach循环打断。

MDN官方文档:

注意: 除了抛出异常以外,没有办法中止或跳出 forEach() 循环。如果你需要中止或跳出循环,forEach() 方法不是应当使用的工具。

我们将上述代码改写:

const array = [1, 2, 3, 4];
const callback = function(element) {
    console.log(element);

    if (element === 2)
      return; // would this make a difference? no.
}
for (let i = 0; i < array.length; i++) {
    callback(array[i]);
}
// Output: 1 2 3 4

这就是上述代码实际的执行思路,return操作只作用于当前的函数,自然不会对for循环产生影响

2. 不能break

下面的代码你觉得会被break掉么?

const array = [1, 2, 3, 4];
array.forEach(function(element) {
  console.log(element);

  if (element === 2)
    break;
});
// Output: Uncaught SyntaxError: Illegal break statement

不会,甚至这行代码都不会运行,直接报错了。

那么这段代码如何达到我们原本想达到的效果呢?

用普通for循环就好了:

const array = [1, 2, 3, 4];
for (let i = 0; i < array.length; i++) {
  console.log(array[i]);

  if (array[i] === 2)
    break;
}
// Output: 1 2

3. 不能continue

下面代码会是跳过2只打印1、3、4吗?

const array = [1, 2, 3, 4];
array.forEach(function (element) {
  if (element === 2)
    continue;

  console.log(element);
});
// Output: Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement

同样不会,和break一样,报错,这行代码之后甚至都不会运行。

怎么达到预期呢?

还是使用普通的for循环来解决:

for (let i = 0; i < array.length; i++) {
  if (array[i] === 2)
    continue;
  console.log(array[i]);
}
// Output: 1 3 4

译者补充

forEach函数的实际运行原理其实是这样的,伪代码如下:

let arr = [1, 2];
arr.forEach(function(ele) {
    console.log(ele);
});
// output: 1, 2
// 上面代码等同于
function func(ele) {
  console.log(ele);
}
for (let i = 0; i < arr.length; i++) {
    func(arr[i])
}
// output: 1, 2

实际上forEach的polyfill实现也是这样的,在forEach函数中执行一个for循环,在for循环里调用回调函数。

因此,像下面代码自然不会符合预期:

let arr = [1, 2];
let sum = 0;
function add(a) {
    return a;
}
arr.forEach(async function(ele) {
  sum += await add(ele);
});
console.log(sum);
// Output:0

改写如下:

let arr = [1, 2];
let sum = 0;
function add(a) {
    return a;
}
for (let i = 0; i < arr.length; i++) {
    sum += await add(arr[i]);
}
console.log(sum);
// Output:3


订阅更多文章可关注「前端进阶学习」,回复「666」,获取一揽子前端技术书籍

原文地址:https://www.cnblogs.com/jztan/p/12316573.html

时间: 2024-10-05 05:50:47

「译」forEach循环中你不知道的3件事的相关文章

「译」一起探讨 JavaScript 的对象

「译」一起探讨 JavaScript 的对象 原文地址:Let's explore objects in JavaScript 原文作者:Cristi Salcescu 译文出自:阿里云翻译小组 译文链接:github.com/dawn-teams/- 译者:灵沼 校对者:也树,眠云 一起探讨 JavaScript 的对象 对象是多个属性的动态集合,它有一个链接着原型的隐藏属性(注:__proto__). 一个属性拥有一个 key 和一个 value . 属性的 key 属性的 key 是一个唯

「译」JavaScript 的怪癖 1:隐式类型转换

原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 [此贴子是 javascript 的 12 个怪癖(quirks) 系列的第一篇.] JavaScript 是非常宽容的,「来者不拒」,不在乎什么类型. 例如,它如果想要接受数字,它并不拒绝其他类型的值,而是试图把它们转换成数字: > '5' - '2' 3 > '5' * '2' 10 自动转

C#不允许在foreach循环中改变数组或集合中元素的值(注:成员的值不受影响)

C#不允许在foreach循环中改变数组或集合中元素的值(注:成员的值不受影响),如以下代码将无法通过编译. foreach (int x in myArray) { x++; //错误代码,因为改变了元素的值 Console.WriteLine(x); } 如果要让自定义的数据类型支持foreach循环,则该类型必须实现IEnumerable<T>接口,且存在对应此列表的IEnumerator<T>实现. 实际上,在.Net的底层(IL语言层面)而言, foreach (var

12 在Foreach循环中如何获得当前迭代的索引

static void ForEachIndex() { int curIndex = 0; Dictionary<string, string> diction = new Dictionary<string,string>(); int counter = 0; diction.Add("One", "One"); diction.Add("Two", "Two"); diction.Add(&qu

C#在foreach循环中修改字典等集合出错的处理

C#在foreach循环中修改字典等集合出错:System.InvalidOperationException: Collection was modified; enumeration operation may not execute.这是因为在foreach中不允许修改集合,可通过如下方式修改dictPublish的值,如: Dictionary<string, string> _dict = new Dictionary<string, string>(dictPublis

在foreach循环中使用remove报ConcurrentModificationException异常原因

在foreach循环中使用remove报ConcurrentModificationException异常原因 我的代码具体是这样的 int dindex=0; int did=getInt("请输入需要删除的学生学号:"); for (Student student:list) { if(student.id==did){ list.remove(student); } } 这样会导致remove后,导致list在循环中下标和实际已经被修改后的下标不一致 我自己的解决方案是: int

关于左撇子你不知道的6件事

1.Left-handers are more likely to develop schizophrenia. A whopping 20 percent of schizophrenics are said to be left-handers, which is a strong proportion considering they only make up 10 percent of the world's population. What's more, being left han

关于“foreach循环”中遇到的几个问题总结

1.列表页面用"foreach循环"的时候数据没有显示,此时需要检查你对象模型中属性的首字母是否大写,切记不能大写(本人在做一个项目的时候,对象模型是别人建立的,属性首字母大写了,导致最后列表页面数据不显示,后来一问老师,说改为小写,瞬间好了).2.数据存储不到表里:在映射文件中没有指定数据表列名的时候,数据表列名必须和属性名相同(应用于hibername操作数据库中). 3.用foreach的时候,从其他页面跳到本页面数据内容不显示,此时在其他页面中必须把跳转到本页面的路径改为浏览器

【PHP】 foreach循环中变量引用的一道面试题

$a = array('a','b','c'); foreach($a as &$v){} foreach($a as $v){ } var_dump($a); 现在.不要打开浏览器,猜测一下.输出的结果是什么? 对引用比较了解的童鞋可能已经看出来了.正确答案是: array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "b"}  也