Why is JSON.stringify not serializing prototype values?

Simply because this is the way JSON works. From the ES5 spec:

Let K be an internal List of Strings consisting of the names of all the own properties of value whose [[Enumerable]] attribute is true.

This makes sense, because there is no mechanism in the JSON specification for preserving information that would be required to parse a JSON string back into a JavaScript object if inherited properties were included. In your example, how would this parsed:

{ "initialisedValue" : "You can see me!", "uninitialisedValue" : "You can't see me!" }

There is no information to parse it into anything other than a flat object with 2 key-value pairs.

And if you think about it, JSON is not intended to map directly to JavaScript objects. Other languages must be able to parse JSON strings into simple structures of name-value pairs. If JSON strings contained all the information necessary to serialize complete JavaScript scope chains, other languages may be less capable of parsing that into something useful. In the words of Douglas Crockford on json.org:

These [hash tables and arrays] are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangeable with programming languages also be based on these structures.


I'd like to add that, even though JSON.stringify will only stringify the object's own properties, as explained in the accepted answer, you can alter the behavior of the stringification process by specifying an array of String as the second parameter of JSON.stringify (called a replacer array).

If you specify an array of String with the whitelist of properties to stringify, the stringification algorithm will change its behavior and it will consider properties in the prototype chain.

From ES5 spec:

  1. If PropertyList is not undefined, then

    a. Let K be PropertyList.

  2. Else

    a. Let K be an internal List of Strings consisting of the names of all the own properties of value whose [[Enumerable]] attribute is true. The ordering of the Strings should be the same as that used by the Object.keys standard built-in function.

If you know the name of the properties of the object to stringify beforehand, you can do something like this:

var a_string = JSON.stringify(a, ["initialisedValue", "uninitialisedValue"]);
//  a_string == { "initialisedValue" : "You can see me!", "uninitialisedValue" : "You can't see me!" }