2012-03-09 97 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