Ext JS: A Reminder About Private JavaScript Members

JavaScript supports private methods. You do not mark them private as in Java: you create them as private and this was described nicely by Douglas Crockford more than 10 years ago. If you ignore the mechanism of private JavaScript methods you raise chances that methods of your objects will be accidentally overridden.

In this blog I’ll just remind you about this issue using the examples with Ext JS framework. My main message is this: carefully select a name for your method because if it’s already used in the objects you’re inheriting from you may get a surprise caused by the fact that not all properties or methods of Ext JS objects are documented. For experimental purposes I’ve created an Ext JS Button object and counted its methods and properties during the runtime. I did it this way:

var b = Ext.create('Ext.button.Button', {
    text:'OK',
    handler: function() {
        console.log('click!');
    }
});
var  props = 0, methods = 0;
for (var name in b) {
    if (typeof b[name] == 'function') methods++;
    else props++;
}
console.log('props: ' + props + ' methods: ' + methods);

Let’s compare the documented and real numbers:

The number of actual runtime properties is 84.
The number of documented properties is 12.
The number of documented configs is 88.

The number of actual runtime methods is 250.
The number of documented methods is 124.
The number of template methods is 20 (they are not included in the Button’s online documentation, even though there is a vague mentioning about them in the component hierarchy Web page).

As you can see 106 methods (250 – 124 – 20) can be considered of unknown data access level, but they are still sitting inside the component silently waiting for conflicts if you’ll extend the Button and will use one of this hidden names.

There are different ways to deal with this. First, always name methods in a unique way – use a meaningful name or some prefix. Second, use Javascript Module Pattern to define ExtJS config object.

In the first example the methods started with “private” could potentially override the methods with the same name if declared in Ext.button.Button. They are also public and are subject to accidental overriding in the subclasses of MyButton.

Ext.define(“MyButton”, {
  extends: “Ext.button.Button”,

  text: 'Click me',

  statics: {
    privateStaticMethod: function() {
      console.log(‘static method’);
    }
  },

  privateMethod: function() {
    console.log(this.getText());
  },

  // will be called when the button was clicked
  handler: function() {
    this.self.privateStaticMethod();
    this.privateMethod();
  }

});

A proposed private method implementation is shown below. It’ll prevent from accidental overriding. Instead of passing the object to the constructor of my button I pass anonymous function and call it immediately (see the last pair of parens in the code below), which includes my methods inside.

Ext.define(‘MyButton’, (function(){
  function privateStaticMethod() {
    console.log(‘static method’);
  }

  function privateMethod(me) {
    console.log(me.getText());
  };

  function privateMethod2() {
    console.log(this.getText());
  }

  return {
    extends: ‘Ext.button.Button’,
    text: 'Click me',

    // will be called when the button was clicked
     handler: function() {
      privateStaticMethod();
      privateMethod(this);
      privateMethod2.apply(this);
    }
};

})()
);

For developers who are used to statically typed languages with the classical inheritance this turn can raise eyebrows – welcome to the World of Javascript. It’s worth mentioning that the “privateMethod” and “privateMethod2” have different invocation syntax as first one uses the explicit parameter “me” for referencing the object instance while the other one uses scoped “this” to refer to the object instance.

Although sometimes the Module Pattern is considered dangerous and can create problems if a class is poorly designed, in such cases you can put these methods into a separate namespace “privates”.

Ext.define('MyButton', {
    extends: ‘Ext.button.Button’,

    text: 'Click me',

    privates: {

      privateStaticMethod: function() {
        console.log('static method');
      },

    privateMethod: function(me) {
        console.log(me.getText());
      },

      privateMethod2: function() {
        console.log(this.getText());
      }

    },

  handler: function() {
    // invoking the methods from the privates namespace
    this.privates.privateStaticMethod();
    this.privates.privateMethod(this);
    this.privates.privateMethod2.apply(this);
  }
});

The private methods calls require some extra coding, but they’ll simplify unit testing of your code. The privates namespace is accessible and you can write test classes that will invoke them as opposed to the Module Pattern approach, where these methods would be not accessible.

On the side note, the private methods are included in the ECMAScript 6 “Harmony” proposal. I’m looking forward to ES6.

To learn more about the proper way of architecting enterprise applications attend our 2 day Ext Js workshop in June in New York City. Enter AlexO as a promo code to get $100 off the price.

Alex Oleynik