2

This overrides console.log without issue and it makes sense to me:

(function(c) {
  console.log = function() {
    c.apply(console, arguments);
  }
})(console.log);

This one does not work and I don't understand why:

(function(c) {
  console.log = function() {
    c(arguments);
  }
})(console.log);

I just get a list of properties when I call console.log.

What's the difference?

I need to build the array with arguments in the second one for it to work.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Gary
  • 909
  • 9
  • 26
  • 1
    The modern solution would utilize [`rest parameters`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) rather than the `arguments` object. This will also work with an arrow function. `(function(c) {console.log = (...args) => c(...args);})(console.log);` – pilchard Jan 29 '23 at 17:09
  • Does this answer your question? [Passing arguments forward to another javascript function](https://stackoverflow.com/questions/3914557/passing-arguments-forward-to-another-javascript-function) – pilchard Jan 29 '23 at 17:19

3 Answers3

2

It works if you modify your function like this:

(function(c) {
  console.log = function() {
    // c(...arguments) also works
    c(...Object.values(arguments));
  }
})(console.log);

console.log('hello world')

This is because arguments is not an array, but an array-like object.

function func(...args) {
    console.log(arguments);
}

func(1, 2, "hello", "world")
Fractalism
  • 1,231
  • 3
  • 12
  • 1
    you don't need the `Object.values()` call. The `arguments` object may be spread directly, from the [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments#arguments_is_an_array-like_object): *'... it can be converted to a real Array, using one of `slice()`, `Array.from()`, or `spread syntax`.'* – pilchard Jan 29 '23 at 17:14
  • @pilchard You're right, I have added that to my code, thanks. But I personally prefer adding `Object.values` to be more explicit since spreading objects as function arguments does not work in general. – Fractalism Jan 29 '23 at 17:32
2

The second code example doesn't works as you expect it to because you are passing the arguments object as it is to the console.log function whereas in the first code example, due to the usage of apply(), the properties in the arguments object are passed as a separate argument. In other words, array or an array-like object is spread in to distinct arguments.

The console.log call in the first code example is similar to the following:

console.log(arg1, arg2, arg3, ...)

whereas in the second one, it is as:

console.log({ 0: arg1, 1: arg2, 2: arg3, ... });
Yousaf
  • 27,861
  • 6
  • 44
  • 69
0
(function(c) {
  console.log = function() {
    const a = Array.from(arguments);
    c(a.join(" "))
  }
})(console.log);

This works.

arguments is an object-like so we need to create the string ourselves.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Gary
  • 909
  • 9
  • 26
  • Yes, much better. Thx. – Gary Jan 29 '23 at 16:57
  • 1
    Note that console.log is capable of a lot more than just sticking strings together, this will fail in many use cases. – jonrsharpe Jan 29 '23 at 17:08
  • 1
    joining them forces string coercion which isn't the behavior of `console.log`. Skip the `join` and just spread the array `c(...a)` (or just spread the `arguments` object `c(...arguments)`) – pilchard Jan 29 '23 at 17:10