Private object members via closures

In almost any object oriented language, you can define access levels for variables in objects. You can in JavaScript, too, but it’s not quite as clear cut as adding a “public” or “private” key word to your object definition. Once you understand how closures work, though, it’s pretty obvious how to implement private member properties and methods.We’ll start out with a typical JavaScript object where all of the members are public, both methods and properties.

  1. var Employee = function(name,dept) {
  2.         this.name = name;
  3.         this.dept = dept;
  4. };
  5. Employee.prototype.description = function() {
  6.         return this.name + " is in the " + this.dept + " division.";
  7. };

Unfortunately, this leaves the employee’s name, department, and description method open to overriding and modification by any code, simply by doing this:

  1. var jeff = new Employee("Jeff","Accounting");
  2. document.write(jeff.description());
  3. Employee.prototype.description = "I hacked your object! None of your code that relies on this method will work now.";
  4. document.write(jeff.description());

Line 4 will now result in an error, since modifying the Employee prototype will modify every instance of Employee in the program! And description is now a string instead of a method. Pretty dangerous, right?

The solution is to get description out of the prototype. Unfortunately, this creates a memory overhead - each instance of Employee will have its own instance of the description method (instead of sharing it with other instances of Employee). So use it with caution - especially if you’re creating a bunch of instances!

Here’s the same object rewritten to encapsulate the name and dept members as private, and the description method out of the prototype of the Employee object.

  1. var Employee = function(name,dept) {
  2.         return {
  3.                 getName : function() {
  4.                         return name;
  5.                 },
  6.                 getDepartment : function() {
  7.                         return dept;
  8.                 },
  9.                 description : function() {
  10.                         return name + " is in the " + dept + " division.";
  11.                 }
  12.         };
  13. };

Here we’re returning an object literal of methods. Because of closures, the name and dept variables are kept alive as long as new instance of Employee is kept alive. They can also be accessed as if they were in scope - without the this keyword.

Now, the previous code that broke our original object will not work. It doesn’t fire an error - it is simply ineffective.

Private scope variables become important when you want other developers to inherit your objects, but not be able to break their functionality. This security comes at the price of higher memory use, though, so be careful.

Tags: , ,

Leave a Reply