Почему console.log не работает при передаче в качестве параметра для forEach? - PullRequest
22 голосов
/ 09 марта 2012

Это просто из любопытства, но у кого-нибудь из вас есть идея, почему этот код не будет работать?

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

24 голосов
/ 15 января 2014

Стоит отметить, что в реализации 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.

11 голосов
/ 09 марта 2012

Это работает:

[1,2,3,4,5].forEach(console.log.bind(console));
9 голосов
/ 09 марта 2012

На самом деле, как указал @SLaks, console.log, похоже, использует this для внутреннего использования, и когда он передается в качестве параметра, this теперь ссылается на экземпляр массива.

Обходной путь для этого просто:

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

0 голосов
/ 09 марта 2012

Не могу сказать, что видел этот синтаксис, но я предполагаю, что log ожидает параметр, являющийся сообщением / объектом / etc для входа в консоль.

в первом примере вы просто передаете ссылку на функцию в forEach, что хорошо, если ваша функция не ожидает параметр, который заставляет функцию вести себя так, как ожидалось.Во втором примере вы вводите e, а затем регистрируете его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...