I'm experiencing extremely strange behavior when accessing a property of an object.
Running this code:
console.log(myObj);
console.log(myObj.items);
console.log(myObj);
I get this output in the console:
How could this possibly happen?
I'm experiencing extremely strange behavior when accessing a property of an object.
Running this code:
console.log(myObj);
console.log(myObj.items);
console.log(myObj);
I get this output in the console:
How could this possibly happen?
Share Improve this question asked Jul 18, 2015 at 0:18 ValevalorinValevalorin 4201 gold badge5 silver badges21 bronze badges 8- We probably need more information than that. – Derek 朕會功夫 Commented Jul 18, 2015 at 0:20
- 1 @Derek朕會功夫 Not much information is provided, but the question looks clear to me. Why would JavaScript show a 2-element array in an object, but when the array is accessed directly, it shows a 0-element array? – Maximillian Laumeister Commented Jul 18, 2015 at 0:23
-
@MaximillianLaumeister I mean, are all the
console.log
exactly one after each other? Was the console already opened when the code was executed? They all can contribute to this result. – Derek 朕會功夫 Commented Jul 18, 2015 at 0:24 -
1
are you shure you don't have method called
items
in your object ... prototype is not expanded so i can not see that – Reflective Commented Jul 18, 2015 at 0:26 -
2
@Reflective Clearly from the console
items
is an Array not a function. – Derek 朕會功夫 Commented Jul 18, 2015 at 0:27
3 Answers
Reset to default 9console.log
, during execution, outputs a string representation of the value in the console. Depending on Chrome's mood, it might show something [object Object]
or something like Object {}
. That doesn't matter.
Now note the little blue i
beside it. What it means is that the object has been modified between the time it was logged and the time you expanded it in the console, and it now shows the current value (with the 2 items), not the value during console.log
's execution (no items). You can actually hover on the blue i
to get the explanation.
To replicate the issue, open the console and run this snippet:
var obj = {arr: []};
console.log(obj);
console.log(obj.arr);
console.log(obj);
// by this time, you see 2 object logs, 1 empty array
// (representation differs from time to time)
// > Object
// []
// > Object
obj.arr.push(1,2);
// when you try to expand the objects, an array of 2 items magically appear
// but you still see the empty array ([]) in the log.
This behavior differs across browsers. As far as I remember, Firebug outputs a serialized version when console.log
executes, hence this doesn't happen there.
Debugging the code
To debug this kind of code, you have several options:
The quickest way is to log the stringified version of the object using
JSON.stringify
, likeconsole.log(JSON.stringify(obj))
;The best way is to add a breakpoint via the Sources tab. Browse to your file in the Sources tab of the Dev Tools, and add a breakpoint in that position. Run your code, and it will pause at that point. Use the Scope panel to inspect the variables.
If you can't reach the code using a breakpoint (probably run using
eval
or injected in the console), you can use thedebugger;
statement. Just put it in the code at that position. Run the code and it will pause when it reaches the statement. Use the Scope panel in Sources tab to inspect.
With so little information, I can only assume you're dynamically populating the items
property, making it empty when the 2nd console log runs.
Now you're wondering why it is there in the 1st console log: the console doesn't show the object properties that were there at the time the object was logged, but rather at the time the object entry was expanded in the console, so it could be that the items
were populated after your 2nd console log and before you expanded the 1st one. Try logging the object as a string or a JSON to see its actual state at the time the console log was run.
Bottom line: object properties in the dev console get updated only when you expand the object entry (when you click the arrow) so you're not seeing the actual representation of the object from the time it was logged.
Here's a simple demonstration - see how it can even turn from an array into a string:
var obj = {p: []}
console.log(obj);
setTimeout(function(){
obj.p = "I'm not even an array!";
}, 1000);
You could look at the JSON representation of the object to check, you can do that with:
console.log(JSON.stringify(myObj, null, 2));