Julian F. Weinert
Julian F. Weinert

Reputation: 7560

JavaScript alter function arguments and use for function.apply

I defined a replacement for console.log which basically adds a global int variable to the beginning of the log.

In the function I'm iterating the arguments array backwards until index equals 1 and move each element by one forwards.

Then I'm adding the global int value at index 1 and change the format string, at index 0, to respect the new argument.

When doing this, console.log uses the new format string and argument but seems to ignore the second – originally first – format argument.

So I created some test functions to compare their output behaviour:

var globalInt = 25;
function log() {
    if (arguments.length > 0 && arguments[0].length > 0) {
        var keys = Object.keys(arguments);

        for (var i = keys.length - 1; i > 0; i--) {
            arguments[parseInt(keys[i]) + 1] = arguments[keys[i]];
        }

        arguments['0'] = '%d: ' + arguments['0'];
        arguments['1'] = globalInt;
    }

    console.log('  %s', JSON.stringify(arguments));
    console.log.apply(console.log, arguments);
}
function log_t1() {
    console.log('  %s', JSON.stringify(arguments));
    console.log.apply(console.log, arguments);
}
function log_t2() {
    if (arguments.length > 0 && arguments[0].length > 0) {
        arguments[0] = '%d: ' + arguments[0];
    }

    console.log('  %s', JSON.stringify(arguments));
    console.log.apply(console.log, arguments);
}

log('test "%s"', 'hello world');

log_t1('%d: test "%s"', globalInt, 'hello world');
log_t2('test "%s"', globalInt, 'hello world');


>> 
  {"0":"%d: test \"%s\"","1":25,"2":"hello world"}
25: test "%s"
  {"0":"%d: test \"%s\"","1":25,"2":"hello world"}
25: test "hello world"
  {"0":"%d: test \"%s\"","1":25,"2":"hello world"}
25: test "hello world"

Comparing those functions, their calls, their outputs and especially the equal JSON prints, I really wonder about the first result.

Can someone see any issue in the code or can confirm this behaviour?

Upvotes: 3

Views: 242

Answers (1)

Tamas Hegedus
Tamas Hegedus

Reputation: 29926

You did not alter the length property of the arguments object. The arguments object is not a simple array, it is something different, and does not alter it's own length property when overindexing.

I suggest you to convert the arguments object to an array first, and favour array methods over loops:

var globalInt = 25;
...
function log() {
    var args = Array.prototype.slice.call(arguments, 0);
    if (args.length > 0 && args[0].length > 0) {
        args = ['%d:  ' + args[0], globalInt].concat(args.slice(1));
    }

    console.log('  %s', JSON.stringify(args));
    console.log.apply(console, args);
}

Upvotes: 3

Related Questions