19

I've ran into some really weird behavior with javascript today. I think I got it somehow figured out now, but I'd like to know if what I think is going on is really happening or if there is some other magic involved. So this is my code:

    var SomeObject = {};

    SomeObject.foo = function(a, b) {
       var baz = this.bar(a, b);
       console.log(baz);
       console.log(baz.left);
       SomeObject.magicalStuff(baz);
    };

    SomeObject.bar = function(a, b) {
        return {left: a-b, top: b-a};
    };

    SomeObject.magicalStuff = function(position) {
        position.left = 0;
    };

    SomeObject.foo(100, 50);

The code at jsFiddle

The output of this is something like (depending on the browser):

> Object
50

If you expand the "Object" (in Chrome, Safari or Firefox (Firebug) what you get is:

> Object
    left: 0
    top: -50

Whereas I would expect:

> Object
    left: 50
    top: -50

What I think is going on is that console.log() really just "posts" a reference to the console, which gets read once you click on the "expand" symbol. But doesn't that kind of defeat the purpose of console.log() as a debugging instrument? I always expected console.log() to "snapshot" the stuff I pass to it. It is really surprising to see a statement which comes after the actual console.log() change the output of that very console.log() call.

Or is there something else going on?

Edit: I'm also wondering if there is a sound reason for browser developers to implement console.log like this (I guess there is one, otherwise it wouldn't be consistent across major browsers).

skaffman
  • 398,947
  • 96
  • 818
  • 769
fresskoma
  • 25,481
  • 10
  • 85
  • 128
  • 1
    See https://bugs.webkit.org/show_bug.cgi?id=35801 – Roatin Marth Mar 07 '11 at 18:42
  • @Roatin Marth: I see. But why do they say: "We can't clone object upon dumping it into the console". What technical difficulties occur that I am not able to see? :) – fresskoma Mar 07 '11 at 18:49
  • This is often seen when you try to log an event, since all events are a single object, you're usually looking at the latest mousemove event. – Ruan Mendes Mar 07 '11 at 19:11

3 Answers3

11

Yes, this is what's going on. I would guess it's done to minimize the overhead of console.log() calls. Things could get out of control if every object was deep cloned for every log call.

When I need to workaround this, I either JSON.stringify() or shallow clone the object before passing it to console.log().

Nathan Ostgard
  • 8,258
  • 2
  • 27
  • 19
  • 1
    Yeah guess you're right. Nevertheless I think that, console.log() being a debug feature and all, it should deep clone. That would be less surprising at least ;) – fresskoma Mar 07 '11 at 18:46
  • JSON.stringify can have problems with HTML elements, since they have circular references. In that case I used outerHTML of the element. – Gábor Lipták Jan 08 '15 at 15:10
11

There is console.dir() for what you want in Firebug.

In general, it is not possible to print every level of nested properties, since objects can contain circular references like var a = {}; var b = {a: a}; a.b = b;

Implementing a perfect clone method is very hard - I guess it would have to basically just dump the whole memory, and logging would take awfully long. Think about console.log(window)...

user123444555621
  • 148,182
  • 27
  • 114
  • 126
  • You've got a point there. Is there something similar for Webkit browsers such as Safari and Chrome? – fresskoma Mar 07 '11 at 22:45
  • I don't think so. As the [above-mentioned bug report](https://bugs.webkit.org/show_bug.cgi?id=35801) suggests, this is a wontfix, and sure enough Firefox's `console.dir()` just pushes the problem to the next level – user123444555621 Mar 08 '11 at 13:26
  • Please note that `console.dir` may not work in Chrome. Here's a comparison of solutions - http://jsfiddle.net/luken/M6295/ - try running it in Chrome. – Luke Mar 06 '14 at 23:38
6

I've also seen this behavior and it sure looks like a reference is posted. To get around this I used the clone() method in jQuery on the things I wanted to log.

jimmystormig
  • 10,672
  • 1
  • 29
  • 28