163

In Safari with no add-ons (and actually most other browsers), console.log will show the object at the last state of execution, not at the state when console.log was called.

I have to clone the object just to output it via console.log to get the state of the object at that line.

Example:

var test = {a: true}
console.log(test); // {a: false}
test.a = false; 
console.log(test); // {a: false}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    jsfiddle example of the problem and various solutions given below: http://jsfiddle.net/luken/M6295/ – Luke Mar 06 '14 at 23:36
  • 10
    It is extremely counterintuitive for the *log* function to output a live reference to the object. That is called a *watch*, which is much different than a log entry. It doesn't make any more sense to do this when logging an object than it would when logging a variable storing a primitive value. – faintsignal Nov 11 '16 at 22:17
  • 2
    How have I never some across this before? I find this frightening – ErikAGriffin Feb 17 '17 at 11:42

12 Answers12

182

I think you're looking for console.dir().

console.log() doesn't do what you want because it prints a reference to the object, and by the time you pop it open, it's changed. console.dir prints a directory of the properties in the object at the time you call it.

The JSON idea below is a good one; you could even go on to parse the JSON string and get a browsable object like what .dir() would give you:

console.log(JSON.parse(JSON.stringify(obj)));

evan
  • 4,239
  • 1
  • 18
  • 18
  • 42
    For me in Chrome13 no difference between `console.log` and `console.dir` – Andrew D. Sep 12 '11 at 14:24
  • Hm, that's surprising- it works in Firebug. I had thought it was the same in Webkit. – evan Sep 12 '11 at 15:12
  • 1
    What I'm seeing in Chrome is that if you open the console after the log statement has run, then it'll do the lazy evaluation when you expand it. But if the console is already open (e.g. you open the console and then hit refresh on the page), it'll do eager evaluation -- i.e. print the value at the time the log statement was run. – Polemarch Jan 14 '14 at 22:26
  • 6
    Also, dir is to JSON as shallow-copy is to deep-copy. console.dir() will only evaluate the top-level object's properties (other more deeply nested objects wouldn't be evaluated), whereas JSON will go recursively. – Polemarch Jan 14 '14 at 22:29
  • 9
    Likewise for me `console.dir` does not work in Chrome (v33). Here's a comparison of the solutions that people have offered: http://jsfiddle.net/luken/M6295/ – Luke Mar 06 '14 at 23:34
  • I didn't experience the effect that Polemarch did. I had the console open all the time, and `console.dir` still didn't behave differently from `console.log`. – Magne May 08 '14 at 13:32
  • console.dir() gave me an expanded listing in firefox, which is not the case with console.log(). Can I have them both collapsed? – Anders Lindén Jan 19 '15 at 09:55
  • Usually `console.dir()` does the trick, but today is showing only a little tooltip that when hovered, says "Object state below is captured upon first expansion". What? – jerome Feb 27 '15 at 20:31
  • `console.dir` and `console.log` do not seem to behave differently. Relevant: https://code.google.com/p/chromium/issues/detail?id=508719 (Link also clears @jerome's question) – jja Jan 31 '16 at 01:31
  • At the time of writing, `.log` and `.dir` behaved differently. – evan Jul 15 '16 at 21:25
  • In conclusion: console.dir(); don't works (at least in Chrome!) and print the reference too. So you should use the JSON idea: console.log(JSON.parse(JSON.stringify(obj))); (as mentioned second in evans answer) – phil Nov 04 '16 at 08:39
74

What I usually do if I want to see it's state at the time it was logged is I just convert it to a JSON string.

console.log(JSON.stringify(a));
Alex Turpin
  • 46,743
  • 23
  • 113
  • 145
  • 4
    Great, that was a nice hint for me : I just had to parse it again to have my object right in the console. `function odump(o){ console.log($.parseJSON(JSON.stringify(o))); }` – Chris Mar 29 '13 at 19:37
  • 1
    thanks this works for me! console.dir didn't print it – ah-shiang han Mar 06 '14 at 04:18
  • 1
    what if your object happens to contain a circular structure? – Alex McMillan Sep 09 '14 at 23:35
  • 1
    @AlexMcMillan You could use [one](https://github.com/isaacs/json-stringify-safe) [of](https://github.com/WebReflection/circular-json) [several](https://github.com/StewartAtkins/JSON-Circular) libraries that allow for JSON stringification of objects with circular references. – Alex Turpin Sep 11 '14 at 01:21
  • 8
    Geez. This should be a simple, obvious thing to be able to do. Instead we have to stringify, parse, log, and use a special circular reference library!?! I think the browsers need to do a better job of supporting simple debugging needs. – Mars Mar 20 '15 at 21:04
32

Vanilla JS:

@evan's answer seems best here. Just (ab)use JSON.parse/stringify to effectively make a copy of the object.

console.log(JSON.parse(JSON.stringify(test)));

JQuery specific solution:

You can create a snapshot of an object at a certain point in time with jQuery.extend

console.log($.extend({}, test));

What is actually happening here is jQuery is creating a new object with the test object's content, and logging that (so it will not change).

AngularJS (1) specific solution:

Angular provides a copy function that can be used to the same effect: angular.copy

console.log(angular.copy(test));

Vanilla JS wrapper function:

Here is an function which wraps console.log but will make a copy of any objects before logging them out.

I wrote this in response to a few similar but less robust functions in the answers. It supports multiple arguments, and will not try to copy things if they are not regular objects.

function consoleLogWithObjectCopy () {
  var args = [].slice.call(arguments);
  var argsWithObjectCopies = args.map(copyIfRegularObject)
  return console.log.apply(console, argsWithObjectCopies)
}

function copyIfRegularObject (o) {
  const isRegularObject = typeof o === 'object' && !(o instanceof RegExp)
  return isRegularObject ? copyObject(o) : o
}

function copyObject (o) {
  return JSON.parse(JSON.stringify(o))
}

example usage: consoleLogWithObjectCopy('obj', {foo: 'bar'}, 1, /abc/, {a: 1})

Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149
8

That > Object in the console, isn't only showing the current state. It actually is deferring reading the object and it's properties until you expand it.

For example,

var test = {a: true}
console.log(test);
setTimeout(function () {
    test.a = false; 
    console.log(test);
}, 4000);

Then expand the first call, it will be correct, if you do it before the second console.log returns

Joe
  • 80,724
  • 18
  • 127
  • 145
2

using Xeon06's hint, you may parse his JSON in an object, and here is the log function I now use to dump my objects :

function odump(o){
   console.log($.parseJSON(JSON.stringify(o)));
}
Chris
  • 1,016
  • 1
  • 14
  • 18
2

There is an option to use a debugger library.

https://debugjs.net/

Just include the script into your web page and put log statements.

<script src="debug.js"></script>

Logging

var test = {a: true}
log(test); // {a: true}
test.a = false; 
log(test); // {a: false}
Takashi Harano
  • 294
  • 1
  • 3
  • 10
1

I defined an utility:

function MyLog(text) {
    console.log(JSON.stringify(text));
}

and when I want to log on console I simply do:

MyLog("hello console!");

It works very well!

Migio B
  • 405
  • 1
  • 6
  • 22
1

You might want to log the object in a human readable way:

console.log(JSON.stringify(myObject, null, 2));

This indents the object with 2 spaces at each level.

How can I pretty-print JSON using JavaScript?

Community
  • 1
  • 1
Andrew
  • 18,680
  • 13
  • 103
  • 118
0

There's a new option as of late 2022: Deep copy the object with the new DOM structuredClone method:

console.log(structuredClone(obj))

which uses the same cloning algorithm that's used to transfer messages between web workers.

This should be faster and work with more types of objects than the JSON.parse(JSON.stringify(obj)) technique.

See https://developer.mozilla.org/en-US/docs/Web/API/structuredClone for details.

Maian
  • 528
  • 2
  • 5
  • 11
-1

I may be shot for suggesting this, but this can be taken one step further. We can directly extend the console object itself to make it more clear.

console.logObject = function(o) {
  (JSON.stringify(o));
}

I don't know if this will cause some type of library collision/nuclear meltdown/rip in the spacetime continuum. But it works beautifully in my qUnit tests. :)

Dave
  • 1,057
  • 2
  • 12
  • 18
-2

Simply refresh the page after you open the console or open the console before you submit the request to the targeted page....

A. Qaoud
  • 33
  • 2
-5

Just print whole object on console.

console.log(object);

see console screen shot for ref

Mangesh Bhapkar
  • 393
  • 1
  • 4
  • 8
  • This displays the state of the object at the current time, not at the time of logging. – Andrew Oct 15 '21 at 17:42
  • Please add some explanation to your answer such that others can learn from it. If `console.log()` prints unexpected output, how does your answer help to resolve this? – Nico Haase Feb 09 '22 at 10:49