Weird behaviour in chrome object console.log - javascript

When I try to console.log an object in Chrome, it states in the first line of the console.log (where you see Object { small summary here } that my posts array is of length 0 (posts: Array[0]).
However when I expand the post it shows that it has 27 items in it (which is what I need).
This happens to me randomly and I got no idea why it is happening, anybody experienced this before?
Screenshot:
Update: This happens in all browsers, so it is probably not chrome related

The debugger can't know if an object has been altered, this is why the posts attribute's rendering (in your example) has not been updated. Even if the debugger would be able to know when a attribute has been changed updating it every time (and all "loggings") would be too expensive.
So the debugger will check the attribute only when accessing it explicitly.
Chrome in this case will do this even only once:
p = []; window.x = {x: p};
Object {x: Array[0]}
x: Array[0]
__proto__: Object
x.x.push(1);
1
x.x.push(2);
2
Klicking x, the Array updates
p = []; window.x = {x: p};
Object {x: Array[2]}
x: Array[2]
0: 1
1: 2
length: 2
__proto__: Array[0]
__proto__: Object
Adding one item more to the array and toggleing x again, the size and entries remain
x.x.push(3)
3
x: Array[2]
0: 1
1: 2
length: 2
__proto__: Array[0]
In my opinion it's not necessary for the logger to update the object value since the variable watch has this function already. There you can always update the current value of a variable.
This works in Firebug and Chrome. Here's an example for Chrome:

The answer of "try-cache-finally" is correct too but I want to contribute the answer that caused the problem to happen in the first place.
when you have this code:
var b = [];
function a(callback) {
if (b.length > 0) {
return callback();
}
doXhr(function() {
b.push("something");
})
}
when you now call a twice then the second call will not see the updated a because of the XHR requests still being in process, this causes the xhr request to be called twice.
The solution for this is to wait on the callback for a like this:
a(function() {
a(function() {
// Correct trigger
});
});
So actually basic async programming, but this error was because of an already existing code base with this bug in it and it was hard to track down.

Related

Changing an array within an object (and vice versa) changes all references to that array before and after the change [duplicate]

This question already has answers here:
console.log() async or sync?
(3 answers)
Closed 6 years ago.
In JavaScript, it appears if I define an array, print that array to the console, then change the array, then print to the console again, the two printings will appear different. Same for objects. This makes sense to me - the first time I print it, it hasn't changed yet, and the second time it has been changed.
However, through testing I've found that if I define an object within an array, print it, change the object, then print again, both printings will be the same (they will both be the changed version). Similarly if I define an array within an object, print it, change the array, then print it again, both printings will be the same (they will both be the changed version).
I think this may be related to passing by reference or by value? But I'm unclear how to relate that concept here. Some articles that I think may be related to my answer:
(SO) Is JavaScript a pass-by-reference or pass-by-value language?
(SO) Javascript by reference vs. by value
http://snook.ca/archives/javascript/javascript_pass
If anyone could help explain I would be very appreciative. Here are the tests I wrote to exemplify what discrepancy I'm asking about:
// Testing changing an array
// RESULT: Array console.logs are DIFFERENT before and after the change.
var arr123 = [1,2,3];
console.log(arr123);
arr123[0] = 4;
arr123[1] = 5;
arr123[2] = 6;
console.log(arr123);
// Testing changing an object
// RESULT: Object console.logs are DIFFERENT before and after the change.
var obj123 = {
first: 1,
second: 2,
third: 3
};
console.log(obj123);
obj123.first = 4;
obj123.second = 5;
obj123.third = 6;
console.log(obj123);
// Testing changing an object inside of an array.
// RESULT: Array console.logs are THE SAME before and after the change, reflecting the change.
var arrOfAnObj = [
{first: 1, second: 2, third: 3}
];
console.log(arrOfAnObj);
arrOfAnObj[0].first = 4;
arrOfAnObj[0].second = 5;
arrOfAnObj[0].third = 6;
console.log(arrOfAnObj);
// Testing changing an array inside of an object.
// RESULT: Object console.logs are THE SAME before and after the change, reflecting the change.
var objOfAnArr = {
arr: [1, 2, 3]
};
console.log(objOfAnArr);
objOfAnArr.arr[0] = 4;
objOfAnArr.arr[1] = 5;
objOfAnArr.arr[2] = 6;
console.log(objOfAnArr);
In all your cases you are modifying the initial object, it's just related to how and when the browser reads the object you passed it through console.log().
Explanation
I executed your code in this repl and the results are always different there.
I executed in chrome and I could reproduce you case. So it has to do with when the browser reads your variable. Because in the first two cases the variable has only one level so chrome shows you the values inline, and therefore reads the object at the point where it is logged.
In the last two cases you have one more level so chrome reads the object reference when you expand the object in the console.
Also I noticed that chrome displays your logs differently whether you run your code while the dev tools are open or when you run your code before opening the dev tools.
If you run the code before opening the dev tools you get the following output:
Whereas if you open the dev tools before running the code you get the following output:

chrome debugger inconsistency in object data

I don't understand how to interpret this debug data. I do a console.log of my object, and on the summary-line that appears in the console I am shown windows: array[0] but if I expand the object, I am shown that windows is an array of 2 items.
Which is the correct one?
My code seem to run on the summary version, ie. windows array being empty.
Does anyone know what my problem is - why is the object presented in an inconsistent way?
The object is being mutated between when you print it and when you view it. When it's initially logged, it's empty but by the time you open it, 2 items have been added.
var obj = { arr: [] };
console.log(obj); // Will say { arr: Array[0] }
obj.arr.push(1); // Open it up in the console after this
Basically, the dev tools print a string that's representative of it's state at the time of the log but it stores a reference to the object in the console itself.

When does the javascript console evaluate the contents of a printed object?

I have found that when using console.log on a nested object the result seems to print after subsequent operations have performed, but only when logging an object with a depth of at least two.
Consider the following example:
function addNumbers(data) {
data.container.firstNumber++
console.log(data); // 3
data.container.firstNumber++
}
var numberData = {
container : {
"firstNumber": 1
}
};
console.log(numberData); // 3
addNumbers(numberData);
I assumed that with this example I would see numberData printed with the values 1 and then 2. In actuality, the value is 3, 3. My first thought was perhaps there is some race condition here where the values changes before the log operation can complete, but if you add more specific references to the object, you will get the value that matches the console.log's position in the code like this:
function addNumbers(data) {
data.container.firstNumber++
console.log(data.container); // 2
data.container.firstNumber++
}
var numberData = {
container : {
"firstNumber": 1
}
};
console.log(numberData.container); // 1
addNumbers(numberData);
Why doesn't the variable evaluate to its value relative to the position of the console.log in the first example, but does in the second example?
relevant fiddle
Most browsers only fetch the properties of an object logged to the console when you expand the object -- and often note this in a tooltip next to the object reference.
They also tend to only expand the object the first time and cache from then on, so the console is not a reliable way to inspect objects.
To get around this, browsers offer a watch panel that will update more frequently and can be used with breakpoints or stepping to get the current state of an object repeatedly.

Strange behavior with a Javascript array, object and RaphaelJS

I have a situation of defining an object with an array in it. For some reason Chrome adds artifacts to that object before I try to use it.
My Object:
var colorPalettes = {
single_A7DBD8: {
amounts: [100],
colors: ['#A7DBD8']
},
single_C02942: {
amounts: [100],
colors: ['#C02942']
}
}
When I run the code, the console shows the following content for var colorPalettes:
amounts: Array[1]
0: Object //<-- added by Chrome, 'value' should come directly in the array
order: 0
value: 100
valueOf: function (){return this.value}
__proto__: Object
length: 1
__proto__: Array[0]
colors: Array[1]
0: "#A7DBD8"
length: 1
__proto__: Array[0]
__proto__: Object
The questions are:
Why does amounts have an Object inside the array? - I didn't define it.
If so - why isn't colors demonstrating the same behavior?
Why is this behavior not demonstrated in my code when I run it through jsfiddle?
What did I try:
In my code colorPalettes is set as window.something.colorPalettes. I turned it into a local variable - no success.
I tried swapping the order of amounts and colors (I know, I was desperate...) - so the behavior also swapped, now colors had the extra Object.
I put my code into http://jsfiddle.net/2JfyX/4/ but the behavior was normal - no extra Object inside colorPalettes.
Edit 1:
I also tried to put a string inside amounts instead of its current int.
Edit 2:
Tried to simulate adding a jQuery click event as in my code, was not able to reproduce http://jsfiddle.net/2JfyX/19/
Edit 3:
I believe I have found the culprit. It is g.Raphael. For some reason (didn't delve into their code yet), it makes changes to the object I pass to it
You can see that I directly pass colorPalettes to r.piechart and in the 6th loop it changes my array to contain an object. Not nice :-O
I will clone the arrays from now on and hope for the best...
function renderPalettes(colorPalettes, radius) {
var gap = radius + 20;
for (var palette in colorPalettes) {
var paletteObj = r.piechart(gap, 43, radius, colorPalettes[palette].amounts, {
colors: colorPalettes[palette].colors,
stroke: "#cdcdcd",
strokewidth: '0.3'
});
for (var i = 0; i < paletteObj.series.items.length; i++) {
paletteObj.series.items[i].node.setAttribute('class', palette + ' sliderPalette');
}
gap = gap + radius * 2 + 24;
}
}
Any idea? Thanks,
D.
I just ran this code in FireFox Firebug. I did console.log() on the object and the following result was displayed.
This pretty much explains the whole situation. The object has two nested objects inside it single_A7DBD8 and single_C02942 Both these objects contain two arrays. "amounts" and "colors".
As you can see the + sign with each array. It shows that these contain elements and we can expand these to see elements at each index of the array.
So if you want to access the first element of amounts array in first object execute this code:
console.log(colorPalettes.single_A7DBD8.amounts[0]);
Remember colorPalettes contains two objects

Array containing objects has wrong length

I have an array like:
errors = [ {...}, {...}, {...} ]
It's an instanceof array, yet it only returns 1 for .length?
Relevant code:
if(data.error){
errors.push({'element':ele,error:data.error});
}
//Above is looped a few times and there are N number of errors now inside
console.log(errors) //Returns 2+ objects like {...}, {...}
console.log(errors.length) //Returns 1
For Uzi and Muirbot, here's the errors array:
[
Object
element: b.fn.b.init[1]
error: "You must enter "example" into the field to pass"
__proto__: Object
,
Object
element: b.fn.b.init[1]
error: "Crap!"
__proto__: Object
It is correct, this code:
var errors = new Array();
errors.push({'element':'ele', error:'data.error'});
...adds ONE object to the array. The object has two properties.
It's possible your code is executing in an order other than what you're expecting. ie, when you log both errors and errors.length, errors does contain only 1 object. But after that you are adding to the errors array, and only after that are you looking at the console. At that point you could see a larger array in errors for two reasons - first, your actual code isn't logging errors but some object that contains errors. In that case the console display is live, and will show you not what was in errors at the time, but what is in it now. Alternatively, the console could just be taking some time to log errors.
Without more code I can't be sure if this is the case. But you could verify it by replacing console.log(errors); with console.log(errors[1]);. If errors is really only 1 long at the time, it will log undefined.
The problem was that Chrome's Web Inspector's console.log is an async event. So, the length was a property lookup so it gave that back instantly, but the object with two items inside was held off until the rest of the events had fired.
In the future I, and others with this issue, should use debugger; instead.
is it an Array object or something that resembles it?
arrays do work:
> a = [{a:1}, {b:2}]
[Object, Object]
> a.length
2
you'll have to provide more code.
and now that you've provided the relevant code, the correct answer is what Steve Wellens said (which was downvoted, by the way).
Array.push adds a single element, objects may have more than one key but they're still a single object so your real case was different from your original example, which of course works.
another possibility:
> a = []
[]
> a.length = 2
2
> a
[]
> a.length
2
> a instanceof Array
true

Categories

Resources