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

时间:2012-03-09 18:30:56

标签: javascript arrays function foreach

这只是出于好奇,但您是否知道为什么这段代码不起作用?

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

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

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

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

所以...?

4 个答案:

答案 0 :(得分:24)

值得指出的是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 ]

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

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

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

在这种情况下,bind 工作:

 > [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 ]

但还有另一种方法:请注意 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 ]

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

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

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

答案 1 :(得分:11)

这有效:

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

答案 2 :(得分:9)

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

解决方法就是:

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

答案 3 :(得分:-4)

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

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