Brad Brad - 3 months ago 17
Javascript Question

Serializing Coordinates: Object.keys() fails on instances of native interfaces?

I have some JavaScript running in Chrome using the Geolocation API:

navigator.geolocation.watchPosition((pos) => {
console.log(pos.coords);
console.log(Object.keys(pos.coords);

}, (err) => {
alert('Geolocation error.\n' + err.message);

}, {
enableHighAccuracy: true
});


When Chrome detects a change in location, it fires off the first callback. This is working well.

The problem comes when I try to do something with that data. When the callback is fired, on my console I will first be able to see the Coordinates object where I called
console.log(pos.coords)
:


Coordinates {latitude: 5.520007, longitude: 13.404954, altitude: null, accuracy: 150, altitudeAccuracy: null, …}


However, the next line where I call
console.log(Object.keys(pos.coords))
, I get an empty array:


[]


Likewise, if I try to use
JSON.stringify(pos.coords)
, I just get an empty object
{}
.

Is there any reasonable way to loop through the keys of
pos.coords
? Must I make my own list of keys to loop through?

Answer Source

Object.keys(pos.coords) gets an empty array

Yes, the properties of the Coordinates interface are implemented as getters on the prototype object (instead of own properties), so Object.keys doesn't find them.

Is there any reasonable way to loop through the keys of pos.coords?

You can in fact just loop through them:

for (const p in pos.coords)
    console.log(p);

An alternative is to use

Object.getOwnPropertyNames(Object.getPrototypeOf(pos.coords));

Do you have a guess as to why they did it this way?

I suspect they're getters that access the internal native data representation linked from the host object. That way, they're implicitly readonly as the spec for the interface requires. They should have been able to achieve that by simply making them own, non-writable data properties either, though.