JavaScript: instance specific read only property with module pattern

The module pattern is a nice way to structure Javascript. It minimizes the use of global variables, enhances the script with private variables and public variables (which is very useful if you’re writing code that someone else will use along the way!). Let’s get a bit more hand-on about this.

Lets say that I’m modeling a (playing) card. It can either face up or down, which is indicated with a bool facingUp. The card may have other properties or dependencies that makes me want any developer that uses my card implementation to call the flip() function that, amongst other things, sets the facingUp property. Allright, so private prop seems like a good idea (and sure, we have that in a lot of other languages).

However, I think the objects gets a bit more slick if you can access properties without writing your own private variable and a getter. So, all of a sudden there is a need for read only props. It is indeed tricky to handle “this” in javascript, and it took me some time to get this working:

var Card = (function() {
  //constructor
  var card = function(settings) {
  settings = settings || {};

  // public properties
  Object.defineProperty(this, "imgSrc", { get: function() { return settings.imgSrc || ""; } });
  Object.defineProperty(this, "facingUp", { get: function() { return false; }, configurable : true });
};

    // instance specific function
    var flip = function () {
        var newValue = !this.facingUp;
        Object.defineProperty(this, "facingUp", { get: function () { return newValue; }, configurable: true });
    };

    card.prototype = {
        constructor: card,
        flip: flip,
    };

    return card;
})();

Object defineProperty

I read about this method  at Mozillas dev-pages. The descriptor has a few interesting literals, namely

  • get, that is a function that acts like a getter
  • configurable: which is a bool that indicates if any aspect of the property may change after it is defined. In my case, I want to be able to redefine it to the “new value” when calling flip.

Define read only in constructor

I tried to define the read only prop in the constructor, but that would not go. Sure, I could define facingUp : false there, but then I would not get the read only property.

Update read only in flip()

This took me some time to get right. The first argument in defineProperty is the object which you want to extend/manipulate. since the card prototype has a public flip literal that points to the flip method, “this” be the instance of the card. Hence this as the first parameter in the call to defineProperty

Avoiding eternal loop

The first thing that happens in the flip function is that the new value is extracted from the old value. My ambision was to make the function a nice one liner that defined “facingUp” as !facingUp – however, it turned out to be a bad idea to read the property in the getter redefine function.

Here’s the jsfiddle!

Comments are closed.