Getting methods on an instance - javascript

From the following code:
let n = 1234.567;
console.log(Object.getOwnPropertyNames(Number.prototype));
console.log(Object.getPrototypeOf(n));
console.log(Object.getPrototypeOf(5));
The first console.log prints the properties, but the second and third line just print {}. Why is this so? Is there a name to directly inspect the variable or number without having to refer to the base type, such as Number.prototype ?

The second and third line only appear to print empty objects due to how the Stack Snippet console operates - the actual browser console of Chrome, Firefox, Safari, or whatever browser you wish will be much more informative. When debugging things and logging objects, if you want the most informative interface, use the actual browser console.
Both of those lines really do point to Number.prototype:
console.log(
Object.getPrototypeOf(5) === Number.prototype
);

Related

Object property value changes before code exectuion [duplicate]

I was helping a colleague debug some code today and I noticed a strange behavior with console.log() in Google Chrome:
It appears that if you:
Create a nested array (e.g., [[345,"test"]])
Log the array to the console with console.log().
Modify one of the inner array values, then console.log() will output the later value -- not the values of the array at the time the console.log() was executed.
JavaScript:
var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]
var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}
var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]
JSFiddle Example
This behavior does not happen in Firefox.
Also to note, if I stepped through his code line by line in the Chrome debugger, then console.log() would output the correct values.
Is there an explanation for this strange phenomenon or is it just a bug with Google Chrome?
EDIT:
I've narrowed down the steps to reproduce the inconsistent console.log() behavior:
If you add this script to your page:
var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
greetings.push('goodbye');
},3000);
and open it in a new window with the Chrome console window already open, then the console.log() output will be different than if you load the page with the console window closed. Here's a JSFiddle that demonstrates that.
In the first case, with the console window already open, console.log() will output the current value of the array (i.e., two items).
In the second case, with the console window initially closed and opened only after the page loads, console.log() will output the later values of the array (i.e., three items).
Is this a bug in Google Chrome's console.log() functionality?
After a lot of digging, I found that this has been reported as a bug, fixed in Webkit, but apparently not yet pulled into Google Chrome.
As far as I can tell, the issue was originally reported here: 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.
A fix was implemented two and a half years later on August 9th, 2012 for Webkit ( http://trac.webkit.org/changeset/125174 ), but it does not appear to have made it into Chrome yet.
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.
I found a workaround for this bug/feature.
console.log(JSON.parse(JSON.stringify(myObject)));
Edit: Unfortunately this won't work for non-primitive values like functions. Use another clone utility here.
jQuery example:
console.log($.extend({}, myObject));

Window object containing variable property before declaration (with value) [duplicate]

I was helping a colleague debug some code today and I noticed a strange behavior with console.log() in Google Chrome:
It appears that if you:
Create a nested array (e.g., [[345,"test"]])
Log the array to the console with console.log().
Modify one of the inner array values, then console.log() will output the later value -- not the values of the array at the time the console.log() was executed.
JavaScript:
var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]
var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}
var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]
JSFiddle Example
This behavior does not happen in Firefox.
Also to note, if I stepped through his code line by line in the Chrome debugger, then console.log() would output the correct values.
Is there an explanation for this strange phenomenon or is it just a bug with Google Chrome?
EDIT:
I've narrowed down the steps to reproduce the inconsistent console.log() behavior:
If you add this script to your page:
var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
greetings.push('goodbye');
},3000);
and open it in a new window with the Chrome console window already open, then the console.log() output will be different than if you load the page with the console window closed. Here's a JSFiddle that demonstrates that.
In the first case, with the console window already open, console.log() will output the current value of the array (i.e., two items).
In the second case, with the console window initially closed and opened only after the page loads, console.log() will output the later values of the array (i.e., three items).
Is this a bug in Google Chrome's console.log() functionality?
After a lot of digging, I found that this has been reported as a bug, fixed in Webkit, but apparently not yet pulled into Google Chrome.
As far as I can tell, the issue was originally reported here: 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.
A fix was implemented two and a half years later on August 9th, 2012 for Webkit ( http://trac.webkit.org/changeset/125174 ), but it does not appear to have made it into Chrome yet.
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.
I found a workaround for this bug/feature.
console.log(JSON.parse(JSON.stringify(myObject)));
Edit: Unfortunately this won't work for non-primitive values like functions. Use another clone utility here.
jQuery example:
console.log($.extend({}, myObject));

Google Chrome console.log() inconsistency with objects and arrays

I was helping a colleague debug some code today and I noticed a strange behavior with console.log() in Google Chrome:
It appears that if you:
Create a nested array (e.g., [[345,"test"]])
Log the array to the console with console.log().
Modify one of the inner array values, then console.log() will output the later value -- not the values of the array at the time the console.log() was executed.
JavaScript:
var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]
var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}
var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]
JSFiddle Example
This behavior does not happen in Firefox.
Also to note, if I stepped through his code line by line in the Chrome debugger, then console.log() would output the correct values.
Is there an explanation for this strange phenomenon or is it just a bug with Google Chrome?
EDIT:
I've narrowed down the steps to reproduce the inconsistent console.log() behavior:
If you add this script to your page:
var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
greetings.push('goodbye');
},3000);
and open it in a new window with the Chrome console window already open, then the console.log() output will be different than if you load the page with the console window closed. Here's a JSFiddle that demonstrates that.
In the first case, with the console window already open, console.log() will output the current value of the array (i.e., two items).
In the second case, with the console window initially closed and opened only after the page loads, console.log() will output the later values of the array (i.e., three items).
Is this a bug in Google Chrome's console.log() functionality?
After a lot of digging, I found that this has been reported as a bug, fixed in Webkit, but apparently not yet pulled into Google Chrome.
As far as I can tell, the issue was originally reported here: 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.
A fix was implemented two and a half years later on August 9th, 2012 for Webkit ( http://trac.webkit.org/changeset/125174 ), but it does not appear to have made it into Chrome yet.
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.
I found a workaround for this bug/feature.
console.log(JSON.parse(JSON.stringify(myObject)));
Edit: Unfortunately this won't work for non-primitive values like functions. Use another clone utility here.
jQuery example:
console.log($.extend({}, myObject));

Array-like objects and arrays not logged like arrays if the console is closed

See this jsbin where, to answer another question, I build an array-like object :
function myCollection() {
var items = [], r = {}
function myPush(value){
value += 'bar'
r[items.length]=value;
items.push(value)
}
Object.defineProperty(r, "splice", {value:[].splice});
Object.defineProperty(r, "slice", {value:[].slice});
Object.defineProperty(r, "length", {
get : function(){ return items.length}
});
Object.defineProperty(r, "myPush", {value:myPush});
return r;
}
var fooCollection = myCollection();
fooCollection.myPush('foo');
console.log(fooCollection); // logs ["foobar"]
fooCollection.myPush('Ba');
console.log(fooCollection); // logs ["foobar", "Babar"]
fooCollection.myPush('wzouing');
console.log(fooCollection.slice(-2)); //logs ["Babar", "wzouingbar"]
console.log(fooCollection[1]); // logs Babar
If you hit the Run with JS button on Chromium with the console open, you get this :
The very curious thing is that if you hit the button while the console is closed you get this (you see it after having reopened the console, of course) :
Is that a known bug ? A feature ? A grey zone ? Is there a workaround ?
*Note : sometimes, on Chrome/linux (not Chromium) I get something weirder : existing logs are changed when closing and reopening the console. They can go from the array like form to the folded form. *
I suppose this behaviour could be an intended one to save memory/performance, since resolving/printing runtime objects is a pretty expensive task.
If you really need an unwrapped info, I'd suggest using
console.dir( myStuff );
Or, alternatively, for arrays there is a new
console.table( myArray );
TIP: console.dir is is also the way to log the object contents in Internet Explorer, as opposed to it's default log() output of [object Object].
It's more like an issue at: https://bugs.webkit.org/show_bug.cgi?id=35801
Seems it's already fixed in webkit.
The very curious thing is that if you log an object while the console is closed, you don't get the expanded (array-like) view (after having reopened the console, of course).
Is that a known bug? A feature?
A feature, I'd guess. The console is optimized for performance while it is not opened, and therefore does not compute that expanded view of the object
Is there a workaround?
Have a look at How can I change the default behavior of console.log? (*Error console in safari, no add-on*). You'd have the typical lazyness problem anyway. Logging JSON strings should help.

Cross-window Javascript: is there a right way?

Problem
I'm trying to make a method that passes objects to a similar method in a popup window. I don't have control over the code in the target method, or the object passed in. The target method currently serialises the object, using JSON.stringify where possible, or instanceof Array.
The first problem with this is a bug in IE8 (see below). The second, and more fundamental, is that primitives are not the same across windows:
w = open("http://google.com")
w.Array == Array // returns false
Overriding on the popup any classes that might be passed in, and then restoring them after the call works, but it's really brittle and a maintenance headache.
Serialising the object into JSON and then parsing it in the context of the window hits the Firefox bug below.
I'm also a bit loathe to do a deep copy of the object or parse the JSON using new w.Object, etc. because it doesn't feel like it should be that complicated.
Can anyone suggest a sensible way to deal with this, or should I just accept that objects can't be passed verbatim between windows?
IE bug
JSON.stringify doesn't work across windows in IE8. If I pass an object to the popup, which attempts to serialise it, stringify returns undefined. To see this problem, open the script console in IE8 and try:
w = open("http://google.com")
JSON.stringify(Object()) // returns "{}"
w.JSON.stringify(w.Object()) // returns "{}"
w.JSON.stringify(Object()) // returns "undefined" on IE8
JSON.stringify(w.Object()) // returns "undefined" on IE8
JSON.stringify([1, w.Object()]) // returns "[1,null]" on IE8
I tried working around this by setting w.JSON = JSON, but as the last test shows, that breaks when you have objects from both windows.
Firefox bug
It seems that calling w.Object() to create an object in Firefox in fact calls window.Object(). The same bug is hit when calling w.JSON.parse or w.eval. To see this, open Firebug's console and try:
w = open("http://google.com")
new w.Object instanceof w.Object // returns true
w.Object() instanceof w.Object // returns false on Firefox 3.5
w.Object() instanceof Object // returns true on Firefox 3.5
w.Object.call(w) instanceof Object // returns true on Firefox 3.5
w.JSON.parse("{}") instanceof w.Object // returns false on Firefox 3.5
w.JSON.parse("{}") instanceof Object // returns true on Firefox 3.5
w.eval("[]") instanceof w.Array // returns false on Firefox 3.5
w.eval("[]") instanceof Array // returns true on Firefox 3.5
w.eval.call(w, "[]") instanceof Array // returns true on Firefox 3.5
The only workaround I can see is parsing the JSON string myself.
For what it's worth, this is what I'm doing for now:
Ensure jquery-json is loaded in the popup window
Stringify the object
Call w.$.evalJSON(str), which binds primitives correctly
Pass that result to the method on the popup
Alternatively (if jquery-json is not available), you could inject the following script into the target:
<script type="text/javascript">
function parseJSON(j) {
return JSON.parse(j)
}
</script>
as that will capture the popup's JSON, and not the caller's.
Any better solutions gladly appreciated.
If you are trying to do cross-domain scripting, seems like JSONP might be worth investigating.
I can't say I understand your problem fully, but there's an interesting window.name hack that's worth checking out: http://www.sitepen.com/blog/2008/07/22/windowname-transport/ (the blog post uses dojo but, of course, it can be done with pure JS too). It's safer than JSONP, easy to implement and it seems to work on all browsers.
Basically, it allows you to store any data, of any length in the window.name variable. What's awesome is that this variable doesn't get flushed/cleared on page change/refresh, so with some clever use of iframes you get simple and secure cross-domain transport :)
To see this, open Firebug's console
and try:
Error: Permission denied for <stackoverflow> to get property Window.Object from <google>.
On any line except first one: w = open("http://google.com")
Firefox 3.5.7
Think for a moment: You ar trying to open new window with arbitrary site and send to it data available to js. Seems too insecure to allow this.

Categories

Resources