Подтвердить что ты не робот

Почему консоль не работает при передаче в качестве параметра 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) });

Итак...?

4b9b3361

Ответ 1

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

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

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

Ответ 2

Стоит отметить, что существует разница в поведении при реализации console.log. В node 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 и node для меня. Конечно, я уверен, что вы хотите только значения, поэтому я боюсь, что лучшее решение действительно:

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

Является ли поведение node ошибкой или просто использует тот факт, что console.log не указывается ECMA, является интересным в своем собственном праве. Но различное поведение и тот факт, что вы должны знать, использует ли ваш обратный вызов this, и означает, что мы должны вернуться к прямому кодированию, даже если он является подробным благодаря ключевому слову function.

Ответ 3

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

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

Ответ 4

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

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