为什么console.log作为参数传递给forEach时不起作用?

时间:2022-12-29 16:56:04

This is just out of curiosity, but do any of you have an idea why this code won't work?

这只是出于好奇,但是你们中的任何人都知道为什么这段代码不起作用?

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

// Prints 'Uncaught TypeError: Illegal invocation' in Chrome

On the other hand, this seems to work fine:

另一方面,这似乎工作正常:

[1, 2, 3, 4, 5].forEach(function(n) { console.log(n) });

So... ?

那么......?

4 个解决方案

#1


22  

It's worth pointing out that there is a difference in behavior in the implementation of console.log. Under node v0.10.19 you do not get an error; you simply see this:

值得指出的是,console.log的实现行为存在差异。在节点v0.10.19下,您不会收到错误;你只是看到这个:

> [1,2,3,4,5].forEach(console.log);
1 0 [ 1, 2, 3, 4, 5 ]
2 1 [ 1, 2, 3, 4, 5 ]
3 2 [ 1, 2, 3, 4, 5 ]
4 3 [ 1, 2, 3, 4, 5 ]
5 4 [ 1, 2, 3, 4, 5 ]

This is because the callback to forEach is a three-parameter function taking the value, the index, and the array itself. The function console.log sees those three parameters and dutifully logs them.

这是因为forEach的回调是一个三参数函数,它取值,索引和数组本身。函数console.log看到这三个参数并尽职地记录它们。

Under the Chrome browser console, however, you get

但是,在Chrome浏览器控制台下,您可以获得

> [1,2,3,4,5].forEach(console.log);
TypeError: Illegal invocation

and in this case, bind will work:

在这种情况下,绑定将工作:

 > [1,2,3,4,5].forEach(console.log.bind(console));
 1 0 [ 1, 2, 3, 4, 5 ]
 2 1 [ 1, 2, 3, 4, 5 ]
 3 2 [ 1, 2, 3, 4, 5 ]
 4 3 [ 1, 2, 3, 4, 5 ]
 5 4 [ 1, 2, 3, 4, 5 ]

but there is an alternative way: note that the second parameter to forEach takes the value of this to use in the callback:

但是有一种替代方法:请注意forEach的第二个参数将在回调中使用this的值:

> [1,2,3,4,5].forEach(console.log, console)
1 0 [ 1, 2, 3, 4, 5 ]
2 1 [ 1, 2, 3, 4, 5 ]
3 2 [ 1, 2, 3, 4, 5 ]
4 3 [ 1, 2, 3, 4, 5 ]
5 4 [ 1, 2, 3, 4, 5 ]

which works in the Chrome console and node for me. Of course, I'm sure what you want is just the values, so I'm afraid the best solution is, indeed:

适用于Chrome控制台和节点。当然,我确定你想要的只是价值观,所以我担心最好的解决方案是:

> [1,2,3,4,5].forEach(function (e) {console.log(e)});
1
2
3
4
5

Whether node's behavior is a bug, or it simply takes advantage of the fact that console.log is not specified by ECMA is interesting in its own right. But the varying behavior, and the fact that you have to be aware of whether your callback uses this is important and means we have to fall back to direct coding, even if it is verbose thanks to the keyword function.

节点的行为是否是一个错误,或者它只是利用了ECMA未指定console.log的事实本身就很有趣。但是变化的行为,以及你必须知道你的回调是否使用它的事实很重要,这意味着我们必须回归直接编码,即使由于关键字功能它是冗长的。

#2


11  

This works:

这有效:

[1,2,3,4,5].forEach(console.log.bind(console));

#3


9  

Actually as @SLaks pointed out, console.log seems to be using this internally and when it's passed as a parameter this now refers to the array instance.

实际上正如@SLaks指出的那样,console.log似乎在内部使用它,当它作为参数传递时,现在引用数组实例。

The workaround for that is simply:

解决方法很简单:

var c = console.log.bind(console); [1,2,3,4,5].forEach(c);

var c = console.log.bind(console); [1,2,3,4,5] .forEach(C);

#4


-4  

I can't say I've seen that syntax, but my guess is because log expects a parameter, being the message/object/etc to log in the console.

我不能说我已经看到了这种语法,但我的猜测是因为日志需要一个参数,即消息/对象/等等,以便在控制台中登录。

in the first example, you are just passing a function reference to forEach, which is fine if your function doesn't expect paramater which make the function behave as expected. In the second example you pass in e and then log it.

在第一个例子中,您只是将函数引用传递给forEach,如果您的函数不期望使函数按预期运行的参数,那么这很好。在第二个示例中,您传入e然后记录它。

#1


22  

It's worth pointing out that there is a difference in behavior in the implementation of console.log. Under node v0.10.19 you do not get an error; you simply see this:

值得指出的是,console.log的实现行为存在差异。在节点v0.10.19下,您不会收到错误;你只是看到这个:

> [1,2,3,4,5].forEach(console.log);
1 0 [ 1, 2, 3, 4, 5 ]
2 1 [ 1, 2, 3, 4, 5 ]
3 2 [ 1, 2, 3, 4, 5 ]
4 3 [ 1, 2, 3, 4, 5 ]
5 4 [ 1, 2, 3, 4, 5 ]

This is because the callback to forEach is a three-parameter function taking the value, the index, and the array itself. The function console.log sees those three parameters and dutifully logs them.

这是因为forEach的回调是一个三参数函数,它取值,索引和数组本身。函数console.log看到这三个参数并尽职地记录它们。

Under the Chrome browser console, however, you get

但是,在Chrome浏览器控制台下,您可以获得

> [1,2,3,4,5].forEach(console.log);
TypeError: Illegal invocation

and in this case, bind will work:

在这种情况下,绑定将工作:

 > [1,2,3,4,5].forEach(console.log.bind(console));
 1 0 [ 1, 2, 3, 4, 5 ]
 2 1 [ 1, 2, 3, 4, 5 ]
 3 2 [ 1, 2, 3, 4, 5 ]
 4 3 [ 1, 2, 3, 4, 5 ]
 5 4 [ 1, 2, 3, 4, 5 ]

but there is an alternative way: note that the second parameter to forEach takes the value of this to use in the callback:

但是有一种替代方法:请注意forEach的第二个参数将在回调中使用this的值:

> [1,2,3,4,5].forEach(console.log, console)
1 0 [ 1, 2, 3, 4, 5 ]
2 1 [ 1, 2, 3, 4, 5 ]
3 2 [ 1, 2, 3, 4, 5 ]
4 3 [ 1, 2, 3, 4, 5 ]
5 4 [ 1, 2, 3, 4, 5 ]

which works in the Chrome console and node for me. Of course, I'm sure what you want is just the values, so I'm afraid the best solution is, indeed:

适用于Chrome控制台和节点。当然,我确定你想要的只是价值观,所以我担心最好的解决方案是:

> [1,2,3,4,5].forEach(function (e) {console.log(e)});
1
2
3
4
5

Whether node's behavior is a bug, or it simply takes advantage of the fact that console.log is not specified by ECMA is interesting in its own right. But the varying behavior, and the fact that you have to be aware of whether your callback uses this is important and means we have to fall back to direct coding, even if it is verbose thanks to the keyword function.

节点的行为是否是一个错误,或者它只是利用了ECMA未指定console.log的事实本身就很有趣。但是变化的行为,以及你必须知道你的回调是否使用它的事实很重要,这意味着我们必须回归直接编码,即使由于关键字功能它是冗长的。

#2


11  

This works:

这有效:

[1,2,3,4,5].forEach(console.log.bind(console));

#3


9  

Actually as @SLaks pointed out, console.log seems to be using this internally and when it's passed as a parameter this now refers to the array instance.

实际上正如@SLaks指出的那样,console.log似乎在内部使用它,当它作为参数传递时,现在引用数组实例。

The workaround for that is simply:

解决方法很简单:

var c = console.log.bind(console); [1,2,3,4,5].forEach(c);

var c = console.log.bind(console); [1,2,3,4,5] .forEach(C);

#4


-4  

I can't say I've seen that syntax, but my guess is because log expects a parameter, being the message/object/etc to log in the console.

我不能说我已经看到了这种语法,但我的猜测是因为日志需要一个参数,即消息/对象/等等,以便在控制台中登录。

in the first example, you are just passing a function reference to forEach, which is fine if your function doesn't expect paramater which make the function behave as expected. In the second example you pass in e and then log it.

在第一个例子中,您只是将函数引用传递给forEach,如果您的函数不期望使函数按预期运行的参数,那么这很好。在第二个示例中,您传入e然后记录它。