0

I have a bunch of javascript functions, that trigger upon button clicks. So assuming we have two button s that trigger two methods such as:

 var universal = false;
    var collection = Array(); // assume it has 5 data elements( 0...4) upon page load

    function next()
    {
      if(universal)
         addToArray();

       // do whatever else
    }

    function addToArray()
    {

        console.log(collection);
       // perform some DOM calls,that simply Hide/change position of elements
       var newElement = 'some info';   
       collection.push(newElement);
    }

In the above addToArray() function, it is called upon when 'next' button is clicked and the universal variable is set to true. At this point we enter, addToArray() method and a console.log is invoked to check out 'collection'.

This, at any given point, should be not more than 5 elements since addToArray will eventually add an element to collection but not right at the start. However, the console.log shows that collection has the new element added, which was actually supposed to be added during the addToArray method() not right off the bat.

I know this sounds really goofy, but this is what I am getting. I am trying to understand if asynchronous behavior has anything to do with it.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
Parijat Kalia
  • 4,929
  • 10
  • 50
  • 77
  • 2
    You're using Google Chrome, right? http://stackoverflow.com/questions/10040856/synchronous-console-logging-in-chrome and http://code.google.com/p/chromium/issues/detail?id=50316 – Matt Ball Dec 17 '12 at 22:40

2 Answers2

2

If you're using Chrome, the reason is that console.log logs a live version of the object that updates in the console window when you change it later.

If you change

console.log(collection);

...to

console.log(collection.join(","));

...or probably more usefully

console.log(JSON.stringify(collection));

...you'll see a point-in-time version of the array.

The behavior of console.log is actually quite tricky, although consistent once you get your head 'round it. For instance, consider this code:

var a = [1, 2, 3];

console.log("first");
console.log(a);
console.log("second");
a[0] = '11';
a = ['a', 'b', 'c'];
console.log("third");

Live Copy | Source

If you have the console open when you run that, you see:

first
[1, 2, 3]
second
third

...and no amount of clicking on that [1, 2, 3] will show you the "11" the code put at index 0, much less the new array we put in a.

But if you change the

var a = [1, 2, 3];

...to

var a = [[1, 1], 2, 3];

Live Copy | Source

...you see this:

first
>[Array[2], 2, 3]
second
third

...and clicking the arrow next to the array changes it to this:

first
v[Array[2], 2, 3]
    0: "11"
    1: 2
    2: 3
    length: 3
    __proto__: Array[0]
second
third

...which looks a bit non-sensical.

But it does make sense, you have to think in terms of the console having a reference to the thing you asked it to output. It outputs a line for the thing, and that line is static. But because it saw that the object graph went deeper, Chrome put an arrow next to the array so you could expand it. When you click the array, the new lines added to the output are generated then, by looking at the now current version of the object, which has obviously changed since the first line was output. Tricky, eh?

In the comments, epascarello mentions using console.dir instead, but that just makes it even more reliably "live," rather than being a point-in-time record.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 2
    or `console.dir(collection)` – epascarello Dec 17 '12 at 22:43
  • that's interesting. I declared a variable x = 2.0 , outside of my function, logged in console.log(x) and then towards the end of my function I said x = x*2.0, and then console.log(x), in this case, it first spat out 2, and then 4, the way it should be. Why did it not use a live version of the object in this situation ? – Parijat Kalia Dec 17 '12 at 22:44
  • 1
    @ParijatKalia: Because numbers are not reference types. If you do `var a = [1, 2, 3]; console.log(a); a = ['a', 'b', 'c'];` you don't see that change for the same reason you don't see the change to the number. – T.J. Crowder Dec 17 '12 at 22:44
  • ok one more thing, the array consists of objects, so using a join to convert them into a comma separated string is not helpful, any suggestions to break this ? – Parijat Kalia Dec 17 '12 at 22:50
  • @epascarello: I'm not seeing any difference with `console.dir`. I get a live copy of the array with that as well -- actually, a more reliably live copy. – T.J. Crowder Dec 17 '12 at 22:51
  • @ParijatKalia: `console.log(JSON.stringify(collection))` – T.J. Crowder Dec 17 '12 at 22:51
  • (In the above, of course, I meant *primitive* numbers are not reference types. JavaScript does have `Number` as well...) – T.J. Crowder Dec 17 '12 at 22:53
0

Your issue is probably that console.log is asynchronous. Try commenting it out or putting a timeout/breakpoint in that line.

frozenkoi
  • 3,228
  • 22
  • 33