JavaScript – Prototypes, Private Data, & Safe Factories

So, after doing even more research on providing prototypal functions access to private data, I came across this article on the Safe Factory Pattern. It is actually similar to my Accessor Verification pattern that I recommended here on Monday. The quick summary is that by shortening this a bit, you can actually safely achieve private data access from prototypal functions:

(function(global, returnData, undefined) {
  // Variable returnData is for temporarily storing what
  // will be returned from the openMySafe function.
  // "undefined" is defined this way so that to minify it
  // in closure compiler.
  
  // Gets the private data from the safe that was created
  // and returns it.
  function openMySafe(me) {
    returnData = undefined;
    me._();
    return returnData;
  }

  // Determine if caller is a property when a function is
  // executed.
  function callerExists() {
    return !!callerExists.caller;
  }
  callerExists = callerExists();
  
  // Returns a function that will return the provided
  // private data only when returnData evaluates to true.
  function makeMySafe(privateData) {
    function safe() {
      // If the caller of this function is openMySafe,
      // assign privateData to returnData.
      if(callerExists == (safe.caller == openMySafe)) {
        returnData = privateData;
      }
    };
    return safe;
  }
  
  // Create the Person class in the global namespace.
  var PersonPrototype = (global.Person = function(firstName, lastName) {
    this._ = makeMySafe({
      firstName : firstName,
      lastName : lastName
    });
  }).prototype;
  PersonPrototype.getName = function() {
    var pData = openMySafe(this);
    return pData.firstName + ' ' + pData.lastName;
  };
  PersonPrototype.setFirstName = function(firstName) {
    var pData = openMySafe(this);
    pData.firstName = firstName;
    return this;
  };
  PersonPrototype.setLastName = function(lastName) {
    var pData = openMySafe(this);
    pData.lastName = lastName;
    return this;
  };
})(this);

// Test out the code.
var chris = new Person('Chris', 'West');
alert(chris.setFirstName('C.').setLastName('Webber').getName());

// Make sure the private data is not accessible.
var prefix = chris._() === undefined ? 'un' : '';
// Outputs:  "The private data returned is undefined."
alert('The private data returned is ' + prefix + 'defined.');

This Abbreviated Safe Factory Pattern works for the following reasons:

  • The makeMySafe({private_data}) function takes the private data associative array object and uses encapsulation to return a function (safe function) which can assign the value to be returned by a safe opener function.
  • JavaScript is only arguably single-threaded (web-workers and browser events may be the exception but this doesn’t seem to be explicitly stated); no two threads can run at the same time.
  • Since JavaScript is single-threaded (or at least one function should execute fully before another starts), we can rely on one control value to determine when private data can be returned by the safe functions.
  • The openMySafe({person_object}) function…
    1. takes a person object
    2. sets returnData to undefined
    3. calls the safe function produced by makeMySafe({private_data}) (AKA {person_object}._()) to assign the private data object to returnData
    4. returns the value of returnData which should be the private data object

I actually had to add an if statement to the safe function due to the existence of Function.prototype.caller. Without this if statement, rogue code could get a reference to openMySafe which would effectively provide access to the private data of an object. This is actually a deficiency that even exists in the original Safe Factory Pattern

If multiple threads could run at once it would be possible for the incorrect private data to get passed back to the wrong class instance. If you do have to allow your classes to multi-threaded, I would recommend using the Accessor Verification Pattern I suggested in this post.

Again, I invite all JavaScripters to try to find a way to get the private data without modifying the closure. I am personally convinced that using this Abbreviated Safe Factory Pattern is a fullproof way of allowing prototypal functions access to truly private members. If you can find a way to disprove me, though, I would be thoroughly impressed (and would much appreciate it)! 8)

JavaScript – Prototypal Functions & Private Data

A while back many people responded to this post, helping me see that my solution for providing private data access to prototypal functions was incomplete. Since then, I had been playing around with some possible solutions in my head and finally came up with two:

  1. Prototypal Registry
  2. Accessor Verification

Prototypal Registry

Prototypal Registry involves using an associative array of all of the original prototypal functions to make sure that the function that is calling the private data accessor function is authentic. The following source code is an example of a Person class which implements this solution to allow three prototypal functions access to private data:

(function(global) {
  // Get generic hasOwnProperty function just in case it is overwritten.
  var hasOwnProperty = ({}).hasOwnProperty;
  
  // Adds the properties defined in objWithExtensions to objToExtend.
  function extend(objToExtend, objWithExtensions) {
    for(var key in objWithExtensions) {
      if(hasOwnProperty.call(objWithExtensions, key)) {
        objToExtend[key] = objWithExtensions[key];
      }
    }
  }
  
  // Creates a Person class.
  var PersonRegistry = {
    getName : function() {
      var pData = this._('getName');
      return pData.firstName + ' ' + pData.lastName;
    },
    setFirstName : function(firstName) {
      var pData = this._('setFirstName');
      pData.firstName = firstName;
      return this;
    },
    setLastName : function(lastName) {
      var pData = this._('setLastName');
      pData.lastName = lastName;
      return this;
    }
  };
  extend((global.Person = function(firstName, lastName) {
    var pData = {
      firstName : firstName,
      lastName : lastName
    };
    function _(name) {
      return PersonRegistry[name] == _.caller && pData;
    }
    this._ = _;
  }).prototype, PersonRegistry);
})(this);

var chris = new Person('Chris', 'West');
alert(chris.setFirstName('Christopher').setLastName('Webber').getName());

The problem with this first solution is the fact that it cannot be guaranteed to work in all environments. Strict mode, Opera 10, BESEN and Rhino 1.7 don’t support the function “caller” property (better breakdown), thusly preventing this solution from working in those environments. Due to this issue, I started thinking about a different solution.

Accessor Verification

The true issue with my original solution (from this post and this post) was the fact that you could override the private data accessor and steal the secret key that was used by all other private data accessors. This then would give that rogue code access to the private data of instances of all such classes. Accessor Verification prevents rogue outside code from being able to do that. Using this scripting pattern, you create a function which is called to then verify that the private data accessor function hasn’t been tampered with. After the accessor function is verified, it is then called with the secret key (accessible only by code within the closure) to get access to the private data. The following source code is an example of a Person class which implements this solution to allow three prototypal functions access to private data:

(function(key, global) {
  // Creates a private data accessor function.
  function _(pData) {
    return function(aKey) {
      return aKey === key && pData;
    };
  }
  
  // Private data accessor verifier.  Verifies by making sure that the string
  // version of the function looks normal and that the toString function hasn't
  // been modified.  NOTE:  Verification can be duped if the rogue code replaces
  // Function.prototype.toString before this closure executes.
  function $(me) {
    if(me._ + '' == _asString && me._.toString === _toString) {
      return me._(key);
    }
  }
  var _asString = _({}) + '', _toString = _.toString;
  
  // Creates a Person class.
  var PersonPrototype = (global.Person = function(firstName, lastName) {
    this._ = _({
      firstName : firstName,
      lastName : lastName
    });
  }).prototype;
  PersonPrototype.getName = function() {
    var pData = $(this);
    return pData.firstName + ' ' + pData.lastName;
  };
  PersonPrototype.setFirstName = function(firstName) {
    var pData = $(this);
    pData.firstName = firstName;
    return this;
  };
  PersonPrototype.setLastName = function(lastName) {
    var pData = $(this);
    pData.lastName = lastName;
    return this;
  };
})({}, this);

var chris = new Person('Chris', 'West');
alert(chris.setFirstName('Christopher').setLastName('Webber').getName());

The above solution should work in all JavaScript/JScript environments. If the private accessor function is overriden, the call by any prototypal function will fail because the verification function will notice that it has been tampered with and undefined will be returned to the prototypal function as the private data container. Neither by using the previous line of thinking (suggested by Esailija), nor by using any other have I been able to extract private data without modifying the original code (that which appears in the closure). The only time when rogue code could dupe the verifier function is if the rogue code overrides Function.prototype.toString before the closure defining the classes is executed. In that case, though, you may have more issues than just those encountered with your private data becoming public. 😀

I would be interested in seeing if any readers can find a way to get access to the private data object with code that runs after the class is defined. If you are good at JavaScript, and think you can figure it out, let me know, but I believe this is a rock solid solution. 8) Happy hacking!!!

JavaScript – Classes, Private Members, & Prototypal Inheritance

A while back I wrote this post about having classes with prototype functions that have access to private variables. To clarify this discussion, I have created this slideshow which briefly outlines how to accomplish writing JavaScript classes with private members which are accessible by prototype functions. In addition, the following is the JavaScript code that I wrote and tested in the JavaScript Box:

// Closure for defining the `Person` class.
(function(key) {
  // Define Person in global scope
  Person = function(firstName, lastName) {
    // Store private members in one object.
    var privateVars = {
      firstName : firstName,
      lastName : lastName
    };
    
    // Define a getter function that will only return private members
    // for privileged functions.
    this._ = function(aKey) {
      return aKey === key && privateVars;
    };
  };
  
  // Define a getter for the full name.
  Person.prototype.getName = function() {
    var _ = this._(key);
    return _.firstName + " " + _.lastName;
  };
  
  // Define a setter for the last name.
  Person.prototype.setLastName = function(newLastName) {
    this._(key).lastName = newLastName;
    return this;
  };
  
  // Define a getter for the first name.
  Person.prototype.getFirstName = function() {
    return this._(key).firstName;
  };
  
  // Create a `Male` class which inherits the Person prototype functions.
  Male = function() {
    Person.apply(this, arguments);
    this._(key).sex = "male";
  };
  Male.prototype = new Person;
  
  // Define a new `getSex()` function for this class.
  Male.prototype.getSex = function() {
    return this._(key).sex;
  };
  
})({});

// Create two people.
var resig = new Male("John", "Q."),
    crockford = new Person("Douglas", "Crockford");

// Show John's full name.
alert(resig.getName());

// Change John's last name and then show his full name.
alert(resig.setLastName("Resig").getName());

// Get Resig's sex
alert(resig.getName() + " is a " + resig.getSex());

// Show Douglas' first name.
alert(crockford.getFirstName());

If you look closely, you will notice that I even threw in some prototypal inheritance so that you can figure out how to make subclasses that use prototype functions to get access to private variables. I have to admit that this idea came from this post from JavaScript extraordinaire, Dean Edwards. Have fun!!! 8)