The way too handle readonly properties in the prototype.

Xavier MONTILLET xavierm02.net at gmail.com
Sat Sep 17 10:14:03 PDT 2011


Hi,

First of all here's the code that made me thought if this:


function Constructor( ) { }
Constructor.prototype.property = 'prototype';
var object = new Constructor( );
object.property = 'instance';
console.log( object.property );// 'instance'

function Constructor( ) { }
Object.defineProperty( Constructor.prototype, 'property', {
    value: 'prototype'
} );
var object = new Constructor( );
object.property = 'instance';
console.log( object.property );// 'instance'

function Constructor( ) { }
Object.defineProperty( Constructor.prototype, 'property', {
    value: 'prototype',
    writable: false
} );
var object = new Constructor( );
object.property = 'instance';
console.log( object.property );// FF: 'prototype', Chrome: 'instance'

As you can see, the only difference is on the last line.

Let's say you have an object "O", whose prototype is "P".
The difference in the behavior happens if "P" has a readonly
(writable: false) value. Let's call the property "p".
Setting "P.p" is forbidden and reading "O.p" or "P.p" is allowed.
But what about setting "O.p"?
Firefox says you can't while Chrome says you can.

When I say Firefox says, you can't I mean you really can't:

( function ( ) {
    'use strict';
    function Constructor ( ) { }
    Object.defineProperty( Constructor.prototype, 'property', {
        value: 'prototype',
        writable: false
    } );
    var object = new Constructor( );
    object.property = 'instance';// Error: 'object.property is
read-only' (in Firefox)
} )( );

I'm quite sure this is a bug. But I find this behavior interesting.
Defining properties of the prototype with Object.defineProperty lets
you prevent other instances or anything else from modifying common
methods.
But most of the time, at least for methods, you want them to remain
the same for the life of the object.
Here is an example:
Let's say you want to prevent anything stupid from happening to the
methods you need:

function Constructor( ) { }
Object.defineProperty( Constructor.prototype, 'method', {
    value: function ( ) { },
    writable: false
} );

Now, your instances are "safe" since their method can't be removed.
But sometimes, you don't even want the person using the object to be
able to set another next method for you object.
You could prevent him from doing so by doing this:

function Constructor ( ) {
    Object.defineProperty( this, 'method', {
        value: function ( ) { },
        writable: false
    } );
}

but then, your methods won't be shared between instances.

----------------------------------------------------------

To put it in a nuttshell:
- Is it the normal behavior that if a property is protected on the
prototype, you can't set it on the object?
- I think it is a behavior that could be used in some cases, even
though it isn't suited as default behavior.


More information about the es-discuss mailing list