3
  • I want to convert the window.screen attributes and values into a string to send to the back-end. (I could extract the values for each attribute but curious to understand why the below fails)

  • Not sure why JSON.stringify(window.screen) returns "{}".

  • Note that the manually created object orientation_ appears to convert JSON to string fine.

Google Chrome Console-1


  • Experimenting further, I tried copying the object and then deleting the __proto__ object thinking this might be failing the conversion to string. But strangely I am unable to delete any of the keys!

Google Chrome console-2


Update #1:

  1. Based on below tips that circular reference could be the issue... Console-3 Here we see that variable a has a circular reference to itself. Using Flatted(circular JSON parser) we see a gets converted into String but window.screen still doesn't convert.

  2. Based on the docs JSON.stringify(), functions are stringified as null.So functions are not the problem.

console-6

So still not clear on the reason for this behavior.

Kent Pawar
  • 2,378
  • 2
  • 29
  • 42

1 Answers1

1

The JSON.stringify requires object properties to be stringifiable. At first sight unfolding __proto__ part of window.screen on console dump one can notice that each of listed attribute is in fact getter function (like get availHeight: ƒ availHeight()) and produce result as usual. However Object.keys(window.screen) produces empty array that suggests all properties are not enumerable so they cannot be found introspecting object, also by JSON.stringify. In contrast your orientation object that you stringified has regular properties that by default are enumerable.

Simplest way to stringify window.screen, an object with short number of attributes, is to make its copy that call getter each time, and then stringify copy:

var scr = {
    width: window.screen.width,
    height: window.screen.height //... }
JSON.stringify(scr); // --> "{"width":1600,"height":900, ...
andy
  • 757
  • 5
  • 13
  • in fact functions are not the problem, the problem is about internal construction of window object, that in some places refers to itself (so called "circular structures") – Flash Thunder Jun 22 '19 at 11:47
  • @FlashThunder agreed, OP however did not try to stringify `window` object that has self-references, it was about `window.screen` that does not. – andy Jun 22 '19 at 11:51
  • I guess __proto__ returns screen as well and it's part of the screen object. I had that problem few years ago, found a good solution to stringify even a window object, but, can't find it right now, and don't really remember the solution. – Flash Thunder Jun 22 '19 at 11:54
  • Yes, it can be done with replacer function for stringify that collects visited references to avoid looping again, something like [this](https://stackoverflow.com/a/11616993/2151810) – andy Jun 22 '19 at 12:38
  • Thanks @andy. I will certainly be using that as a workaround but still looking to understand the reason for this behavior. I updated my question with an example to show that circular reference is not the cause for this behavior and that functions stringify into null – Kent Pawar Jun 22 '19 at 15:09
  • This has nothing to do neither with getters, neither with circular references, it's just that these properties are not enumerable: https://jsfiddle.net/1nodye3x/ – Kaiido Jun 22 '19 at 15:42
  • @Kaiido you are right, I wrongly used `propertyIsEnumerable` while doing research. Let me reedit my response. Nevertheless there is something more involved, screen has empty prototype chain (does not inherit) yet `Object.getOwnPropertyNames(window.screen)` return empty array, while object with non-enumerable properties should have them listed. – andy Jun 22 '19 at 19:32