Adding new line after bracket

464 views Asked by At

I am proxying the function console.log to add some information to my logs and I am as well checking whether the information being logged is an object. I do this to avoid getting a log entry of the sort

2016-12-17 (22:12:51) > [object Object]

Code works fine when passing arguments that are not objects. For example, the command

console.log("hello","world");

prints

2016-12-17 (22:23:53) > hello
2016-12-17 (22:23:53) > world

But if I pass an object as well, the code will fail to insert a new line after the object. For example, the command

console.log("hello",{world:true,hello:{amount:1,text:"hello"}},"world");

prints

2016-12-17 (22:27:32) > hello
2016-12-17 (22:27:32) > { world: true, hello: { amount: 1, text: hello } } 2016-12-17 (22:27:33) > world

(note the missing line break after displaying the object).

Code

JQuery 3.1.1

main.js:

(function (proxied) {
    function displayArg(argument){
        var result= "";
        if(typeof argument == "object") {
            result += "{ ";
            for (i in argument) {
                result += i + ": ";
                result += (displayArg(argument[i]));
                result += ", "
            }
            result = result.substring(0,result.length - 2);
            result += " }";
            return result;
        } else {
            return argument;
        }
    }

    console.log = function () {
        var result = [];
        for (i in arguments) {
            var d = new Date();
            result[i] = d.getFullYear() + "-" + (d.getMonth() + 1)  + "-" + d.getDate() +
                " (" + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + ") > ";
            result[i] += displayArg(arguments[i]);
            result[i] += "\n";
        }
        return proxied.apply(this, result);
    }
})(console.log);
2

There are 2 answers

0
Emilio On BEST ANSWER

TL;DR change the iterator variables so they don't share name, or add a "var" to the loop definition to make sure they don't escape your desired scope.

It turns out that the for loops from (my own) console.log and displayArg were "sharing" the value of the iterator i. This is because by not declaring the iterator variable, the scope was broader than what I needed. To clarify, look at this example:

console.log({isThis:"real life"},"hello","world")

The code from console.log will add a date to the beginning of result[0] and then call displayArg(arguments[0]), arguments[0] being {isThis:"real life"}. That function, will iterate over the objects properties, thus i will be assigned the value isThis. After the function returns, the value of i will not go back to 0. Instead, i will be isThis and as a consequence, the line

result[i] += "\n";

translates to

result[isThis] += "\n"

instead of

result[0] += "\n"

Probably the most sensible solution was to add a var in the for declaration of the iterators. The following code works as expected:

(function (proxied) {
    function displayArg(argument){
        var result= "";
        if(typeof argument == "object") {
            result += "{ ";
            for (var i in argument) {
                result += i + ": ";
                result += (displayArg(argument[i]));
                result += ", "
            }
            result = result.substring(0,result.length - 2);
            result += " }";
            return result;
        } else {
            return argument;
        }
    }

    console.log = function () {
        var result = [];
        for (var i in arguments) {
            var d = new Date();
            result[i] = d.getFullYear() + "-" + (d.getMonth() + 1)  + "-" + d.getDate() +
                " (" + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + ") > ";
            result[i] += displayArg(arguments[i]);
            result[i] += "\n";
        }
        return proxied.apply(this, result);
    }
})(console.log);
1
charlietfl On

I'm not fully understanding objective but what about something along the lines of the following oversimplified override:

var oldLog = console.log;

console.log= function(){
   var d= new Date(),
       dateString = // process string

   .....
   for(var i = 0; i<arguments.length; i++){
      oldLog(dateString, arguments[i]);          
   }

}