Can Read-Only Properties be Implemented in Pure JavaScript?

Viewed 48863

Looking at the mozilla documentation, looking at the regular expression example (headed "Creating an array using the result of a match"), we have statements like:

input: A read-only property that reflects the original string against which the regular expression was matched.

index: A read-only property that is the zero-based index of the match in the string.

etc... is it possible to create your own object in JavaScript which will have read-only properties, or is this a privilege reserved to built-in types implemented by particular browsers?

9 Answers

Edit: Since this answer was written, a new, better way using Object.defineProperty has been standardized in EcmaScript 5, with support in newer browsers. See Aidamina's answer. If you need to support "older" browsers, you could use one of the methods in this answer as a fallback.


In Firefox, Opera 9.5+, and Safari 3+, Chrome and IE (tested with v11) you can define getter and setter properties. If you only define a getter, it effectively creates a read-only property. You can define them in an object literal or by calling a method on an object.

var myObject = {
    get readOnlyProperty() { return 42; }
};

alert(myObject.readOnlyProperty); // 42
myObject.readOnlyProperty = 5;    // Assignment is allowed, but doesn't do anything
alert(myObject.readOnlyProperty); // 42

If you already have an object, you can call __defineGetter__ and __defineSetter__:

var myObject = {};
myObject.__defineGetter__("readOnlyProperty", function() { return 42; });

Of course, this isn't really useful on the web because it doesn't work in Internet Explorer.

You can read more about it from John Resig's blog or the Mozilla Developer Center.

It is possible to have read-only properties in JavaScript which are available via getter methods. This is usually called the 'Module' pattern.

The YUI blog has a good writeup of it: http://yuiblog.com/blog/2007/06/12/module-pattern/

Snippet from the post:

YAHOO.myProject.myModule = function () {

//"private" variables:
var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";

//"private" method:
var myPrivateMethod = function () {
    YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
}

return  {
    myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty."
    myPublicMethod: function () {
        YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");

        //Within myProject, I can access "private" vars and methods:
        YAHOO.log(myPrivateVar);
        YAHOO.log(myPrivateMethod());

        //The native scope of myPublicMethod is myProject; we can
        //access public members using "this":
        YAHOO.log(this.myPublicProperty);
    }
};

}(); // the parens here cause the anonymous function to execute and return

Here's a link to Douglas Crockford's page on "Private Members in Javascript"....it would seem to me these would be read only if only getter methods are supplied, and no setters:

http://javascript.crockford.com/private.html

If you want a read-only property at runtime without having to enable "strict mode", one way is to define a "throwing setter". Example:

Object.defineProperty(Fake.prototype, 'props', {
  set: function() {
    // We use a throwing setter instead of frozen or non-writable props
    // because that won't throw in a non-strict mode function.
    throw Error();
  },
});

Referenced from React

Related