Pseudo-private Properties

JavaScript does not provide a practical and efficient means of declaring private properties in classes.

The Wrong Way: Technically speaking, there is a means to create private variables and methods using a closure inside of a constructor. Such a technique has the unfortunate side effect of having very poor CPU utilization and memory consumption characteristics. The underlying problem is that the content of the closure must be interpreted each time a new object is created, and each object gets it's very own instance of the private methods. These detriments make such a solution anything but, especially in the case where large numbers of objects are routinely created.

Pseudo-Privacy

While we might not be able to have private properties, there is a means available to ensure that internal variables are not modified outside of a class. There are two requirements to create such a "pseudo-private" variable or method:

  • Name the property with a leading underscore. This syntax convention is used to denote an internal property. It is strictly voluntary. Simply ensure that your class does not invoke any methods or access/mutate any variables that begin with an underscore in any other class. If you see an "_" without the word "this" in front of it, you're doing something wrong.
  • Declare the property as final, i.e., DO NOT place it in a $virtual block. This will prevent any subclass from re-declaring the property. Always specifically declare the property, even if its initial value is null, false, 0, or undefined.

This is a "cooperative" solution. All classes must follow these rules for it to work, but if this policy is adhered to, you will never encounter illegal access to internal methods or variables. When implemented, this policy eliminates the potential for accidentally overriding or modifying an internal variable of a base class.

The following example shows a class with pseudo-private properties:

PrivateExample = Core.extend({

    _internalArray: null,

    $construct: function() {
        this._internalArray = [];
    },

    _internalMethod: function() {
    }
});

Derivative class declarations will fail in the event that any of the internal property names are re-declared. Note that to ensure this, we declare the property _internalArray, even though we're only initializing it to null.