Friday, September 20, 2013

Hiding Privates (Part 2)

In a follow up to my earlier post about not using an underscore to indicate privacy, there is a situation when dealing with instance variables on prototypes that can get a little uglier. However, hiding these are also possible. Take this example.

function UserView(userRepo, console) {
 this.userRepo = userRepo;
 this.console = console;
}

UserView.prototype = {
 render: function () {
  var model;
  
  this.console.log("Rendering UserView");
  model = this.userRepo.getUsers();
  //…
 }
};
Let's say that for whatever reason the userRepo and console objects should not be exposed. Anyone with access to the UserView could then use these directly to do some logging and access the repo without going through dependency injection or whatever module system you have setup. So how do you hide these variables? Glad you're curious. One way is to store them in an object.
(function () {
 
 var privates = {},
     cid = 0;
 
 function UserView(userRepo, console) {
  this.cid = cid++;
  privates[cid] = {
   userRepo: userRepo,
   console: console
  };
 }
 
 UserView.prototype = {
  render: function () {
   var model,
        _ = privates[this.cid];
   
   _.console.log("Rendering UserView");
   model = _.userRepo.getUsers();
   //…
  },
  close: function () {
   delete privates[this.cid];
  }
 };
 
}());
The ugly part of this (besides the photo at the top), is that you need to remember to delete your privates. Don't worry, it won't hurt.

Wednesday, September 11, 2013

Combine - A Dead Simple Form of JavaScript Inheritance/Composition


Some time ago I was working in a very light weight code base and found the need for basic composition with function prototypes. I didn't need or want the typical JavaScript inheritance hack that provides access to the base class via a super method or responded correctly to the instanceof operator (see: Simple JavaScript Inheritance). I just needed to combine two objects and execute their constructors in order.

Wait that is simple:
function combine(parent, child) {
    var constructor = function () {  
        parent.apply(this, arguments);
        child.apply(this, arguments);
    }
    constructor.prototype = _.extend({}, parent.prototype, child.prototype);
    return constructor;
}
The _.extend call is in this case using Underscore.js which is just the basic mixin method.

This gave me exactly what I wanted and with just a few lines of code. The combine function takes parent and child constructor functions and returns a new constructor function which executes them both (parent then child). It also mixes in their prototypes to create a new prototype.

Example of basic usage:
function X() {
    this.prop1 = "parentProp1";
    this.prop2 = "parentProp2";
}

X.prototype = {
    method1: function () {
        return this.prop1;
    },
    method2: function () {
        return this.prop2;
    }
}

function Y() {
    this.prop2 = "childProp2";
}

Y.prototype = {
    method3: function () {
        return this.prop1 + " from child method3";
    }
}

var Z = combine(X, Y);
var z = new Z();
console.log(z.method1());
console.log(z.method2());
console.log(z.method3());

Here is a jsFiddle: http://jsfiddle.net/jhorback/UsNAP/