2

i am facing a strange behaviour in a for loop that contains array of objects

The following is the example

var store = {};
var storesWithTimestamps = [];

for (var i=0;i<2;i++){                      
    console.log("inital list",storesWithTimestamps); //1
    console.log("inital length",storesWithTimestamps.length); //2

    store = {};
    store.latestTimestamp = null;
    store.storeName = "testStore";
    storesWithTimestamps.push(store);

    console.log("new list",storesWithTimestamps); //3
    console.log('new length',storesWithTimestamps.length); //4
}

The problem is log statement 3 shows a array of object with 2 items in the 1st iteration , but the log statement 4 shows the length as 1.

The output of the log statement 3 is the same for both the iteration like this, [{latestTimestamp:null,storeName:"testStore"},{latestTimestamp:null,storeName:"testStore"}]

Where as it should be 1st loop:

[{latestTimestamp:null,storeName:"testStore"}]

2nd loop:

[{latestTimestamp:null,storeName:"testStore"},{latestTimestamp:null,storeName:"testStore"}]

FYI: this works as expected in Safari but not on chrome - OSX Attached fiddle: http://jsfiddle.net/gauravsoni/09Ls3rtx/

Attached screenshot: wrong length

16
  • 1
    jsfiddle.net/arunpjohny/fysnjt74/1 ? looks fine Commented Oct 5, 2015 at 8:20
  • 1
    Working fine in Chrome for me. Commented Oct 5, 2015 at 8:20
  • 1
    The cose is fine, and it works on Chrome. I'm voting for closing because I cannot reproduce the problem. Commented Oct 5, 2015 at 8:23
  • 1
    I actually can see it in the console in js fiddle. But only the first time it runs. The array already has 2 elements Commented Oct 5, 2015 at 8:24
  • 2
    It is due to javascript points objects by reference, so changing the object leads to change it in console. Try to place debugger in the loop and see how your output will change step by step. Commented Oct 5, 2015 at 8:30

3 Answers 3

2

Actually it's due to the Debugger behavior.

If the debugger is opened when you run the script, the output in the console will be correct.

If the debugger is not opened when you run the script, the object is evaluated at the time the console is displayed. That's why you can see 2 objects in the array.

I think it is what @yorlin was meaning.

Addendum: You may want to use the JSON.stringify() method to log the instant object properties:

console.log( "inital list:", JSON.stringify( storesWithTimestamps ) ) //1
...
console.log( "new list:", JSON.stringify( storesWithTimestamps ) ) //3

Nota bene: In the console, italic values were evaluated instantly, while non-italic values are evaluated when they are displayed (as you can see in the blue [ i ] next to the values).

Conclusion: In the second posted screenshot we can see clearly it was not a Chrome bug.

Sign up to request clarification or add additional context in comments.

8 Comments

In my case i have the debugger opened and running the script, its the same no matter what.
@Gaurav_soni, are you sure you cleared the log window before reloading the page? Maybe there's a problem with your browser because noone seems able to reproduce the behavior with console opened. I tested it on Chrome 46 and Firefox with the expected result.
Yes, tried with the console opened/closed , restarted the browser. Same code works fine in safari and firefox. Should be a browser issue on OSX , @sirrocco also seems to be facing the same issue.
Are you on windows or mac ?
I tried it on a windows machine also, same issue there too. With the console opened the new list log shows both the values during the 1st iteration.
|
1

I've tried this....Just like @yorlin and @Supersharp said.

You can check it in console more clear.

var store = {};
var storesWithTimestamps = [];

//Checkout the status of ary
function displayObj(objAry){
    var info="\n";
    for(var i=0;i<objAry.length;i++){
        var data=objAry[i];
        info+='\t\trecord('+i+').id:'+data.id+'\n';
    }
    return info;
}

for (var i=0;i<2;i++){                      
    console.log("inital list",storesWithTimestamps); //1
    console.log("inital length",storesWithTimestamps.length); //2

    //put an id to identify
    store = {id:i};
    store.latestTimestamp = null;
    store.storeName = "testStore";
    storesWithTimestamps.push(store);

    console.log("new list",displayObj(storesWithTimestamps)); //3
    console.log('new length',storesWithTimestamps.length); //4
}

Comments

1

This is happening due to async nature of console.log() you can find more details regarding this behavior at console.log() async or sync?

you can try workaround to log the proper value as below -

var store = {};
var storesWithTimestamps = [];

for (var i=0;i<2;i++){                      
    console.log("inital list",storesWithTimestamps); //1
    console.log("inital length",storesWithTimestamps.length); //2

    store = {};
    store.latestTimestamp = null;
    store.storeName = "testStore";
    storesWithTimestamps.push(store);

    console.log("new list",JSON.stringify(storesWithTimestamps)); //3 instead of passing object, pass serialized snapshot of the object
    console.log('new length',storesWithTimestamps.length); //4
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.