2012-03-09 76 views
21

这仅仅是出于好奇,但你们有一个想法,为什么这个代码将无法正常工作?当作为参数传递的forEach为什么不CONSOLE.LOG工作?

[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

你有错误的'this'。 – SLaks 2012-03-09 18:32:04

+0

确实。将自己回答,我是一个白痴 – 2012-03-09 18:35:48

+0

它可以被删除吗?这不是真的那么有用=/ – 2012-03-09 18:38:02

回答

8

其实作为@SLaks指出,执行console.log好像是用this内部,当它作为一个参数this传递真实,现在指的是阵列实例。

该解决方法很简单:

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

+2

不以节点V6对此的解释工作 – 2016-06-06 13:35:45

-4

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

在第一个例子

,你只是传递一个函数引用的forEach,如果你的函数不期望paramater这使得像预期的那样,其功能是好的。在第二个例子中,你传递e然后记录它。

+2

错误的; 'forEach'传递一个参数。 – SLaks 2012-03-09 18:36:09

+0

我试图让虽然一点是,参数需要传递给尽管CONSOLE.LOG,即执行console.log(_e_) – thescientist 2012-03-09 18:37:21

+1

是的,这正是发生了什么。函数表达式中的函数与属性中的函数没有区别。 – SLaks 2012-03-09 19:08:00

11

这工作:

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

伟大的答案,我想标记为接受,但你能解释(对于那些不知道)你的代码做什么?如果没有,恐怕我不得不接受我的信息。感谢 – 2012-03-09 20:50:18

+2

不在节点V6工作: > [1,2,3] .forEach(console.log.bind(控制台)) 1 0 [1,2,3] 2 1 [1,2,3 ] 3 2 [1,2,3] – 2016-06-06 13:35:05

+0

在Node v7中仍然失败。如果你只是想记录数组的元素,我会避免这种解决方案。这个答案将'console.log'应用于回调函数的三个参数,并打印出非常混乱和不合需要的输出。当答案写入时,它可能会恢复原状,但仅仅是因为特定的JavaScript实现错误,恕我直言。回调最近有三个参数。 – 2016-11-27 07:58:51

21

值得指出的是,存在的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 

无论节点的行为是一个错误,或者是根本没有的优势事实上console.log不是由ECMA规定的是在自己的权利有趣。但不同的行为,你必须要知道你的回调是否使用this是重要的,意味着我们必须回落到直接编码,即使是冗长感谢关键字function的事实。

+0

谢谢 - 读者可能会发现下面的链接,描述了预期的参数Array.prototype.forEach(),并传递给提供的回调ARGS(如你讨论):HTTPS:/ /developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach – arcseldon 2015-12-15 12:33:15

+1

虽然与箭头功能可以使用:'[1,2,3] .forEach(v =>的console.log (ⅴ))'。 ;-) – RobG 2016-11-26 21:01:41

+0

事实上,我无法相信自己仍然在2014年初使用长形函数表达式作为'forEach'(和朋友)的参数。不过,必须在不久之后才会切换。 – 2016-11-27 07:54:58

相关问题