这只是出于好奇,但您是否知道为什么这段代码不起作用?
[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) });
所以...?
答案 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然后记录它。