Bug in console.log? [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Chrome's JavaScript console lazy about evaluating arrays?
I try the following code:
var myList = new Object();
var item = new Object();
item.text = "item-1";
myList[3] = item;
console.log(myList);
console.log(myList[3].text);
// Assign another object to the same entry
var item2 = new Object();
item2.text = "item-2";
myList[3] = item2;
console.log(myList);
console.log(myList[3].text);
The result is quite odd:
* Object
* 3: Object
text: "item-2"
item-1
* Object
* 3: Object
text: "item-2"
item-2
BUT - if i execute the second part after some time (using setTimeout), and unfold the first object, I get it right, i.e.:
* Object
* 3: Object
text: "item-1"
item-1
* Object
* 3: Object
text: "item-2"
item-2
I find it important to share it, since I think one can waste a lot of time trying to understand what's wrong in his code.
And if somebody has some reference to an open bug or something - please reply this ticket.
Thanks!

My view is that this is a horrendously irritating 'feature' that I really wish I could turn off, it makes debugging a nightmare, not knowing at which point in time something may have updated an object, whilst trying to establish exact object state at a give point in the code. The feature could be useful for 'watch points' etc, but not in something called a 'LOG' (the clue is in the name).
Consider this code fragment:
var person = {'name':'Tom'};
console.log( person); //output the entire object variable
person.name = 'Thomas';
//the output is an object, whose 'name' value is 'Thomas', even though the log statement was placed before the value was changed to 'Thomas'.
AND THEN:
var person = {'name':'Tom'};
console.log( person.name); //changed to output a string variable
person.name = 'Thomas';
//the output here, however, has not dynamically updated and correctly outputs 'Tom'

this is a known bug (50316) that gets reported again and again because people don't take a look at the bugtracker before reporting:
78325
94887
105559
107828
111020
131124
sadly, theres no information about if/when this will get solved. until that moment, you'll need to clone objects before passing them to console.log().

Sounds to me more like a race condition than anything else. Since you are only passing a reference to console.log(), the value it refers it has likely changed value by the time it is actually logged. Then when you use setTimeout(), the value changes after it has been logged. Instead of passing a reference to console.log(), pass a clone of the value.

This is a known problem/feature with the console log in some browsers.
When you log something, it may not immediately be turned into text format. If the log stores a reference to the object that you log, it will be turned into text format when it's actually shown in the log.
This has the advantage that logging something has a very small impact on performance, until you actually open the log window to show the log.
Even if you have the log window open while you run the code, there is no updates happening while your function is running (as Javascript is single threaded), so the console window will show the values as they are at the end of the function, when the window is updated.

I have done some experiments with this "problem" on the latest version of Chrome 20.0.1132.57 m.To summarize the key points :-
console.log() prints a reference to the object with as "> Object" when the code is executed
The state of the object when you click on the triangle is displayed, irrespective of the line of code where the console.log() is executed
If you want to print the object in its current state, print a clone console.log(JSON.parse(JSON.stringify(obj)));
You could use this bit of code to test this on your own browser:
window.onload = function() {chto = {a : 10, b : 20};
console.log('Open this object after 5 seconds')
console.log(chto);
console.log('Open this object before 5 seconds')
console.log(chto);
console.log('Console of the cloned object')
console.log(JSON.parse(JSON.stringify(chto)));
setTimeout(function(){ console.log('5 seconds up'); chto['b'] = 30; },5000 ) ; };

Related

Issues with populating arrays from csv(dsv) parsing

I am quite new to javascript, basically using it for the first time to write a histogram plotter application. My issue is, I am importing a data file and ideally sending (some of) the entries into an array. Problem is that once I do that, I have troubles accessing the entries in my array.
How could I fix that? Posting the code below in case it helps.
Thank you!
let filename = 'uploads/testdata.dat';
const data_e = new Array();
d3.dsv(" ",filename, (event)=>{
data_e.push(event.mass);
return data_e
})
console.log(data_e);
Which outputs
Array []
​
0: "734.770828169"
​
1: "85.0912893849"
​
2: "87.383924186"
​
...
However if I wanna get a value:
console.log(data_e[0]) //output: undefined
Edit1: the values I'm pushing are in console.log(event.mass).
output:
734.770828169 analyzer.php:19:12
85.0912893849 analyzer.php:19:12
87.383924186 analyzer.php:19:12
(...)
Edit2: If I call console.log(data_e) inside the dsv function I get a line for each iteration while my array gets filled, ending with
Array(7178) [ "734.770828169", "85.0912893849", "87.383924186", "1274.99805502", "91.5349415148", "80.2766459668", "1396.69489276", "91.5584443363", "94.52017453", "1582.29197222", … ]
Which is, indeed the object I want to get. But what if I want to carry that outside the function dsv(), so that I get the same output as above?
Edit3: Calling console.log(JSON.stringify(event.mass)) gives:
again, one line for each 'iteration' (I think), and it makes sense. I just want to use the full array outside that function (or maybe it's just a silly thing to do .-.)
"734.770828169" analyzer.php:19:12
"85.0912893849" analyzer.php:19:12
"87.383924186" analyzer.php:19:12
"1274.99805502" analyzer.php:19:12
(...)
Do not use return inside the loop, because you then leave it immediately. Whatsmore, I think d3.dsv() is an asynchronous function. Means your console log outside this method must return undefined as Javascript does not wait for d3.dsv() to finish. And your Array data_e is currently undefined.
let data_e = new Array();
Instantiate it this way and you'll see, that console.log() will output [] instead of undefined.
let data_e = [];
d3.dsv(" ",filename, (event)=>{
// your code
})
console.log(data_e);
Actually, I could not find a manual about how to get a trigger when d3.dsv() is finished. But fo the start try it this way. It's not perfect but it's only supposed to show you that it actually works;
let filename = 'uploads/testdata.dat';
const data_e = new Array();
// run the filter
d3.dsv(" ",filename, (event)=>{
data_e.push(event.mass);
})
// wait 2 seconds, then show the array in the console
setTimeout( () => {
console.log(data_e);
}, 2000);

How is it possible to have an array with length 0 but has content?

I have the following test code:
console.log('AA',slider);
console.log('AB',slider.length);
it returns the following in chrome console.
AA Array[53]
AB 0
i added test code because slider[5] always came back with undefined even though the console shows there is a value there.
here is a simplified version of initialisation script. entire code is pretty long and Slider is an object. Code for object is working the test script is later on trying to manipulate specific slider positions based on ajax return data.
var slider=[];
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
var slider={};
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
returns
AA {
1:{m
a: ....,
b: ....,
c: ....,
g: ....,
h: ....
},
2: .....
gets all the way up to 49
Ok i figured out the problem and hopefully this helps others.
After going through the code here is a much better example of initialization
var slider=[];
setInterval(function(){
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
},500);
console.log('AA',slider);
console.log('AB',slider.length);
the array is indeed empty at the time the console log commands are executed but apparently the first line records reference to the object and not current state. So when I look at the log which is always going to be more then half a second later it shows data being there.

console.log/console.dir showing last state of object, not current

I want to log how my array/object is changing with new steps of loop. Console.log does this bad. It shows only last state of object everywhere. For example:
var a = {};
console.log(a); // {bob1: 0, bob2: 0}
a.bob1 = 0;
console.log(a); // {bob1: 0, bob2: 0}
a.bob2 = 0;
console.log(a); // {bob1: 0, bob2: 0}
I found there, on so, another command: console.dir. It is working properly in same example. It shows states of object correcly.
Look this example. This command works perfect: http://jsfiddle.net/RLzVV/
Now, look my code pls. All output is in console. http://jsfiddle.net/3BDs7/4/
This is aStar algorithm. Take a look on this part (neighbor 3 loop <--- neighbor 3 start ---> this code is situated here <--- neighbor 3 stop -->) in console. Lanes, which output this to console are 105-113:
new openset length: 2
openset after adding new vertex
**shows 1 element, but length is 2**
It shows length is 2, but shows only 1 element. But! Seems to me algo is working correctly (it is popping another element, which is hidden on this step after). Why this bug appears? Did I did something wrong? Seems to me, everywhere only last state of array shown, not current:( help me please.
That's a known issue -- sounds like you are running under Chrome.
The easiest work-around is to JSON encode the value as you log in.
console.log(JSON.stringify(a));

Unable to use variable in constructing $pop query in Meteor

I'm trying to use $pop on an embedded array in Meteor and I'm pretty certain that my limited understanding of variable scope and order of operations is causing me issues.
To provide a simplified example, this works:
do_thing = function(foo) {
Coll.update(foo, {$pop: { "bar.baz": 1 }} );
};
do_thing( "123" );
But this does not:
do_thing = function(foo, bar) {
var tmp = bar + ".baz"
Coll.update(foo, {$pop: { tmp: 1 }} );
};
do_thing( "123", "bar" );
The core issue is that the update succeeds when I hard-code the array from which I wish to pop the item, but the update fails when that array is dynamically constructed. I assume the cause is not the fact that it is a variable since 'foo' works, and instead the problem lies in the way that 'tmp' might not be getting instantiated in time for the update() call.
Can anyone suggest how I can achieve the result I'm looking for: popping an item from a field whose name I won't necessarily know until I'm in the function?
Alternately, I'm open to broader suggestions of how to construct this function if I'm taking a completely wrong-headed approach in the first place.
The literal string "tmp" is being used for the key name, rather than the value you are passing in for the variable "tmp".
Try this:
updateboj = {}
updateobj[tmp] = 1
Coll.update(foo, {$pop: updateobj} );

What is the initial value of an initialized Array in Javascript on different systems?

I've been struggling for months with a JavaScript problem where I have an array with a few properties, and later some of these properties are checked to decide whether or not to show a message to the user.
Now this all goes well on most systems (especially more recent browsers) but not so much on some of my client's IE7 computers.
Now I just found out that somewhere in my code I initialize a new Array like below, but never actually set the value for 'done'
var qar=new Array('question_no','pos','done');
qar['question_no'] = 1234;
qar['pos'] = 1234; //dont mind these numbers
Later in some for loop I check:
//check if this question was already shown
if(qar['done'])
continue; //stop here, don't show message
//set done to true, so that this question will not be shown again
qar['done'] = true;
window.alert('messaged!');
Again, what goes wrong is that sometimes (actually pretty often, but not always) the message is not shown at all in IE7.
Now for my question to you: I know that qar['done'] should be undefined right after initialization, which makes my code work fine (in Chrome etc), but could it be that somehow in IE7 this situation is handled differently? For example that qar['done'] is not undefined, but some random value and therefore is sometimes considered true accidentally? Or is that a stupid thing to think?
If this is not the problem, then I don't know what is..
Thanks in advance!
By doing this:
var qar=new Array('question_no','pos','done');
You are just creating array with indexes.
qar[0] will be 'question_no'
qar[1] will be 'pos'
qar[2] will be 'done'
in this case, qas['done'] will always be undefined.
Thats why its causing problems. You should either use javascript object instead of using an array.
But you can do something like this:
if(typeof qar['done'] === 'undefined'){
qar['done'] = true;
alert('messaged!');
}
Your code should be like this:
var qar={};
qar['question_no'] = 1234;
qar['pos'] = 1234; //dont mind these numbers
//check if this question was already shown
if(!qar['done']) {
//set done to true, so that this question will not be shown again
qar['done'] = true;
window.alert('messaged!');
}

Categories

Resources