使用箭头函数遍历数组的forEach循环

7
我想逐行打印数组并换行。简单实现方法是使用[1,2,3].forEach(function(x) {console.log(x)}),以此作为输出结果。
1
2
3

现在,如果我使用ES6箭头函数的语法糖,
michel$ node
> [1,2,3].forEach(x => console.log(x))
1
2
3
undefined
>
> [1,2,3].forEach(console.log)
1 0 [ 1, 2, 3 ]
2 1 [ 1, 2, 3 ]
3 2 [ 1, 2, 3 ]
undefined

forEach 回调函数中省略函数参数时,第二个版本看起来返回了自身的笛卡尔积。

在其他函数式编程语言(如Scala)中,这是完全可以的,为什么在JavaScript中会被认为是“错误”的呢?

michel$ scala
scala> Array(1,2,3).foreach(x => println(x))
1
2
3

scala> Array(1,2,3).foreach(println)
1
2
3

检查 console.log(console.log),你会得到答案。 - Durga
我添加了一个Scala代码示例,以展示我的问题。 - Michel Hua
3个回答

9

看起来这里的代码:

[1,2,3].forEach(console.log)

等同于:

[1,2,3].forEach((value, index, array) => console.log(value, index, array))

这并不是“错误”,只是相比Scala或Java(方法引用),它显得“不寻常”。Javascript似乎只是将所有参数复制到引用的方法中(例如console.log),如果该方法支持可变参数,那么所有参数都会被处理。

但是,如果您不喜欢这种行为,您可以在Javascript中进行修复。创建一个接受单个参数的简单函数:

function print(t) { console.log(t) }

然后执行:

[1,2,3].forEach(print)

这将输出结果,如果你来自Scala背景,你会感到身处家中:

1
2
3

1
相关 https://dev59.com/4mkw5IYBdhLWcg3wzdpE 随着JavaScript语言的发展,答案有些不同。 - Michel Hua
与Scala或Java(方法引用)相比,它只是“不寻常的”,似乎支持仅带有一个参数的方法引用。在Java中,没有任何关于方法引用的内在限制,可以支持多个参数。这种确切情况(forEach调用支持varargs的方法)在Java中也可能存在。 - T.J. Crowder

9
你可以使用ES6的“胖箭头”像这样。
     const data = [1,2,3,4]

     data.forEach(item => {
         console.log(item)
     })

1
forEach 将多个参数传递给回调函数,而不仅仅是一个:项、其索引以及调用 forEach 的对象。大多数 console.log 实现接受多个参数并输出所有参数。这就是为什么 forEach(console.log) 输出条目(1)、其索引(0)和数组([ 1, 2, 3 ]),然后是下一个条目等。使用箭头函数时,您只使用其中的第一个参数。

顺便提一下:forEach(console.log) 也会传递 console.log,但并不确保在调用 logthisconsole。有些控制台实现可能不关心,而有些则会关心。因此,如果您想要第二种形式,最好使用 forEach(console.log, console)


好的,也许在forEach中使用箭头函数是不好的做法,因为我应该收到一个ESLint警告? - Michel Hua
@JohnPoe:我不明白你认为在这里使用箭头函数有什么不对的地方? - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接