Search code examples
javascriptobjectprototype

I don't understand writable and configurable property attributes of Objects


I don't understand the Writable and Configurable attributes of Objects. For example, in the MDN for Object.prototype, there is a table where I can clearly see that Configurable, Writable and Enumerable Property Attributes of Object.prototype are locked.

However, I can write and extend Object.prototype, for example with the following code:

// Example 1
Object.prototype.testing=999;
console.log(Object.testing); // 999

// Example 2
var o = {};
console.log(o.testing); // 999

Solution

  • What the MDN is referring to is the property prototype of Object itself. You cannot overwrite Object.prototype itself. If you try and make Object.prototype undefined, that will fail:

    Object.prototype = 1;
    console.log(Object.prototype); // [object Object]
    

    If you try this in strict mode, you will get a TypeError upon attempting to assign to a non-writable property:

    'use strict';
    Object.prototype = 1; // TypeError: Cannot assign to read only property 'prototype' of function Object() { [native code] }
    

    You can write to an object's own properties without changing what the object's reference is, and those have separate attributes. For example, see this:

    var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'toString');
    
    console.log(descriptor.writable); // true
    console.log(descriptor.enumerable); // false
    console.log(descriptor.configurable); // true
    

    There is a separate [[Extensible]] internal property that prevents the creation of new properties on an object -- this is set to false if you call Object.preventExtensions, Object.seal or Object.freeze.

    Note that it's not a good idea to call Object.freeze on something like Object.prototype, as really weird things can happen:

    Object.freeze(Object.prototype);
    var building = {};
    building.name = 'Alcove Apartments';
    building.constructor = 'Meriton Apartments Pty Ltd';
    console.log(building.constructor); // function Object() { [native code] } 
    

    Just like the previous example, it will also throw a TypeError in strict mode.

    Basically, even though it would be a property on the object itself, it uses the attributes from the prototype chain to check whether or not it can assign the property. This has been considered as a mistake in the language by some people, however others consider this behaviour to be by design.