object as array element-the console log output is confusing [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Chrome's JavaScript console lazy about evaluating arrays?
Chrome's js console is showing an array with a deleted value before the value is deleted. Why?
jsFiddle that demonstrates this behavior.
var list=[];
list.push("one");
list.push("two");
list.push("three");
console.log(list); //["two", "three", undefined × 1]
$("#output").append(JSON.stringify(list));//["one","two","three"]
list.shift();
$("#output").append($("<br>"));
console.log(list); //["two", "three"]
$("#output").append(JSON.stringify(list));//["two","three"]
​

In Chrome console.log is "delayed"; in this case to the end of the Program I believe.
That is, in Chrome, console.log does not stringify the input object immediately but rather performs the stringification "some time later" (after which the object has been modified in this case) but before it actually displays the result,
console.log(JSON.stringify(list)) would show the expected result.
This was reported as a bug as far back as Chrome 5 (the bug-fix target is Mstone-22, so not Chrome 20/21?) and a fix has been added to the webkit base:
As of today, dumping an object (array) into console will result in objects' properties being read upon console object expansion (i.e. lazily). This means that dumping the same object while mutating it will be hard to debug using the console.
This change starts generating abbreviated previews for objects / arrays at the moment of their logging and passes this information along into the front-end. This only happens when the front-end is already opened, it only works for console.log(), not live console interaction.

Related

Can't iterate over my array/object. Javascript, React Native [duplicate]

This question already has answers here:
Is Chrome’s JavaScript console lazy about evaluating objects?
(7 answers)
Closed 5 years ago.
I really don't understand what could be going on here. So I have a function which takes a 2d array and a string and iterates through the 2d array and checks if any subarrays contain the string. But somehow I can't iterate over this object/array and I'm really confused as to what it actually is. I've done lots of iteration in javascript. I've tried for-in, for-of (es6), C stlye(like below), forEach(callback), map... nothing works.
_makeOrUpdateCase = (arrayOfArrays, str) => {
console.log(arrayOfArrays); //returns the object/array shown in image below, expected
console.log(typeof(arrayOfArrays)); //object
console.log(Array.isArray(arrayOfArrays)); //true - huh? is this array or object??
for (var i = 0; i < arrayOfArrays.length; i++) {
console.log(arrayOfArrays[i]) //this does not work
console.log(i); //nothing is printed out, as if the loop is simply ignored
}
Here is the output I get.. you can see that the stuff I'm printing in the loop is not executed. I know javascript can be weird but c'mon what is going on here, I have no idea what to google. I've iterated over arrays and objects lots of times in this code.
tl;dr: Your loop is fine but the array is empty even if it appears in the console that it is not.
You are logging/accessing the array before it was populated. That's evident from the Array[0] in the output (indicating an array of length 0), even though it appears to have an element. This can happen if you have an asynchronous process, like Ajax, but are logging/accessing the array before the asynchronous process is done.
If you hover over the little i in the console, it will tell you that the value was just evaluated, i.e. it shows the value the variable has at the time you click the triangle, not at the time you log the value in code. By the time you click the triangle, the asynchronous process will likely have finished.
However, if you use console.log(JSON.stringify(arrayOfArrays)); instead you will see that the array is empty.
Here is simple example that demonstrates the issue (open the browser console and expand the array, works in Chrome at least):
// Open the browser console
var arr = [];
console.log(arr);
arr.push(1,2,3);
The only solution is to call _makeOrUpdateCase only after the asynchronous process is done. Since you are not showing how/when/where the function is called, this is all that can be said about the problem.
Related: Is Chrome's JavaScript console lazy about evaluating arrays?

JavaScript: Can't access array in object

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?
console.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, like console.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 the debugger; 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.
You could look at the JSON representation of the object to check, you can do that with:
console.log(JSON.stringify(myObj, null, 2));
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);

Why I am getting wrong output when I modify the following Javascript object code? [duplicate]

This question already has answers here:
How can I make console.log show the current state of an object?
(12 answers)
Closed 7 years ago.
This is the javascript code.
var option={
value:'',
desc:{
en:'',
hn:''
}
};
option.value='15';
option.desc.en='hello';
option.desc.hn='world';
console.log(option);
option.value='25';
option.desc.hn='India';
console.log(option);
This gives the output-
object {value:25,object {desc:{en:"hello",hn:"India"}}}
object {value:25,object {desc:{en:"hello",hn:"India"}}}
Instead of
object {value:15,object {desc:{en:"hello",hn:"world"}}}
object {value:25,object {desc:{en:"hello",hn:"India"}}}
the output diff with different browser. I got the
object {value:15,object {desc:{en:"hello",hn:"world"}}}
object {value:25,object {desc:{en:"hello",hn:"India"}}}
through chrome.
Like #Chales Tuang mentioned, I got the expected output on
jsfiddle
var option={
value:'',
desc:{
en:'',
hn:''
}
};
option.value='15';
option.desc.en='hello';
option.desc.hn='world';
console.log(option);
option.value='25';
option.desc.hn='India';
console.log(option);
The only explanation I could possibly think of for the case where you get same output in each call to console.log, is that the browser is applying the principle that objects are live in Javascript, as shown by Stoyan Stefanov in his book Object Oriented Javascript
As a result, the when you call console.log, it sees the latest, up-to-date property(ies) of the object, even though the object was augmented after the call, in as much as the update is within the scope of the call, it just grabs the current updated state of the object.
That's my thought on this, anyway.
This is because of a bug in WebKit browsers (https://code.google.com/p/chromium/issues/detail?id=44720)
Instead of logging the entire object,try to log the particular value, you will get the expected result..
console.log(option.desc.hn);
Or try JSON.stringify
console.log(JSON.stringify(option));
JS Fiddle link : https://jsfiddle.net/t744ohog/2/

Wrong value in console.log [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Chrome's JavaScript console lazy about evaluating arrays?
I have the following snippets in javascript whose output makes me feel that something is going wrong.
1.
a=2;
console.log(a);
a+=2;
console.log(a);
Output:2 4 ; as expected
2.
t=[0,2];
console.log(t);
t[0]+=2;
console.log(t);
Output: [2,2] [2,2]
Shouldn't the output be [0,2] [2,2] ? And whats the difference between the above two cases that results in the different answers in both the cases?
It's because the log is delayed until Chrome has time to do it (i.e. your scripts releases the CPU).
Try this to understand what happens :
var t=[0,2];
console.log(t);
setTimeout(function() {
t[0]+=2;
console.log(t);
}, 1000);
It outputs what you expect.
Is that a bug of Chrome ? Maybe a side effect of an optimization. At least it's a dangerous design...
Why is there a difference ? I suppose Chrome stores temporarily what it must log, as a primary (immutable) value in the first case, as a pointer to the array in the last case.
console.log in chrome/ff is asynchronous and objects that are logged are interpreted at the time when they're expanded. . Instead make a copy of the object if you want to see its value at that time (for an array):
t=[0,2];
console.log(t.slice(0));
t[0]+=2;
console.log(t);
With an array, calling .slice will duplicate the array and not create a reference.
I wouldn't suggest using a time out: this really doesn't solve the problem, just circumvents it temporarily.
Everything you're doing is right, but chrome's logging is screwy/delayed. Try making a copy of the variable and adding to that and you'll see that your code is correct.
Chrome's logging is delayed in the newer versions, no problem from your end. Make a copy of the variable or use setTimeout.

console.log() shows the changed value of a variable before the value actually changes

This bit of code I understand. We make a copy of A and call it C. When A is changed C stays the same
var A = 1;
var C = A;
console.log(C); // 1
A++;
console.log(C); // 1
But when A is an array we have a different situation. Not only will C change, but it changes before we even touch A
var A = [2, 1];
var C = A;
console.log(C); // [1, 2]
A.sort();
console.log(C); // [1, 2]
Can someone explain what happened in the second example?
Console.log() is passed a reference to the object, so the value in the Console changes as the object changes. To avoid that you can:
console.log(JSON.parse(JSON.stringify(c)))
MDN warns:
Please be warned that if you log objects in the latest versions of Chrome and Firefox what you get logged on the console is a reference to the object, which is not necessarily the 'value' of the object at the moment in time you call console.log(), but it is the value of the object at the moment you open the console.
Pointy's answer has good information, but it's not the correct answer for this question.
The behavior described by the OP is part of a bug that was first reported in March 2010, patched for Webkit in August 2012, but as of this writing is not yet integrated into Google Chrome. The behavior hinges upon whether or not the console debug window is open or closed at the time the object literal is passed to console.log().
Excerpts from the original bug report (https://bugs.webkit.org/show_bug.cgi?id=35801):
Description From mitch kramer 2010-03-05 11:37:45 PST
1) create an object literal with one or more properties
2) console.log that object but leave it closed (don't expand it in the console)
3) change one of the properties to a new value
now open that console.log and you'll see it has the new value for some reason, even though it's value was different at the time it was generated.
I should point out that if you open it, it will retain the correct value if that wasn't clear.
Response from a Chromium developer:
Comment #2 From Pavel Feldman 2010-03-09 06:33:36 PST
I don't think we are ever going to fix this one. We can't clone object upon dumping it into the console and we also can't listen to the object properties' changes in order to make it always actual.
We should make sure existing behavior is expected though.
Much complaining ensued and eventually it led to a bug fix.
Changelog notes from the patch implemented in August 2012 (http://trac.webkit.org/changeset/125174):
As of today, dumping an object (array) into console will result in objects' properties being
read upon console object expansion (i.e. lazily). This means that dumping the same object while
mutating it will be hard to debug using the console.
This change starts generating abbreviated previews for objects / arrays at the moment of their
logging and passes this information along into the front-end. This only happens when the front-end
is already opened, it only works for console.log(), not live console interaction.
The latest guidance from Mozilla as of February 2023:
Don't use console.log(obj), use console.log(JSON.parse(JSON.stringify(obj))).
This way you are sure you are seeing the value of obj at the moment you log it. Otherwise, many browsers provide a live view that constantly updates as values change. This may not be what you want.
Arrays are objects. Variables refer to objects. Thus an assignment in the second case copied the reference (an address) to the array from "A" into "C". After that, both variables refer to the same single object (the array).
Primitive values like numbers are completely copied from one variable to another in simple assignments like yours. The "A++;" statement assigns a new value to "A".
To say it another way: the value of a variable may be either a primitive value (a number, a boolean, null, or a string), or it may be a reference to an object. The case of string primitives is a little weird, because they're more like objects than primitive (scalar) values, but they're immutable so it's OK to pretend they're just like numbers.
EDIT: Keeping this answer just to preserve useful comments below.
#Esailija is actually right - console.log() will not necessarily log the value the variable had at the time you tried to log it. In your case, both calls to console.log() will log the value of C after sorting.
If you try and execute the code in question as 5 separate statements in the console, you will see the result you expected (first, [2, 1], then [1, 2]).
Though it's not going to work in every situation, I ended up using a "break point" to solve this problem:
mysterious = {property:'started'}
// prints the value set below later ?
console.log(mysterious)
// break, console above prints the first value, as god intended
throw new Error()
// later
mysterious = {property:'changed', extended:'prop'}
The issue is present in Safari as well. As others have pointed out in this and similar questions, the console is passed a reference to the object, it prints the value of the object at the time the console was opened. If you execute the code in the console directly for example, the values print as expected.
Instead of JSON stringifying, I prefer to spread arrays (e.g. in your case console.log([...C]);) and objects: the result is quite the same, but the code looks a bit cleaner. I have two VS code snippets to share.
"Print object value to console": {
"prefix": "clo",
"body": [
"console.log(\"Spread object: \", {...$0});"
],
"description": "Prints object value instead of reference to console, to avoid console.log async update"
},
"Print array value to console": {
"prefix": "cla",
"body": [
"console.log(\"Spread array: \", [...$0]);"
],
"description": "Prints array value instead of reference to console, to avoid console.log async update"
}
In order to get the same output as with console.log( JSON.parse(JSON.stringify(c))), you can leave out the string part if you wish. Incidentally, the spread syntax often saves time and code.

Categories