even more private methods on prototype

JavaScript performance comparison

Revision 3 of this test case created

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
my method
var defineClass = (function() {

  // Creates a proxying function that will call the real object.

  function createProxyFunction(functionName) {
    return function() {
      // 'this' in here is the proxy object.
      var realObject = this.__realObject__,
          realFunction = realObject[functionName];

      // Call the real function on the real object, passing any arguments we received.
      return realFunction.apply(realObject, arguments);
    };
  };

  // createProxyClass creates a function that will create Proxy objects.
  //   publicFunctions: an object of public functions for the proxy.

  function createProxyClass(publicFunctions) {
    var ProxyClass, functionName, func;

    // This is this Proxy object constructor.
    ProxyClass = function(realObject) {
      // Choose a reasonably obscure name for the real object property.
      // It should avoid any conflict with the public function names.
      // Also any code being naughty by using this property is quickly spotted!
      this.__realObject__ = realObject;
    };

    // Create a proxy function for each of the public functions.
    for (functionName in publicFunctions) {
      func = publicFunctions[functionName];
      // We only want functions that are defined directly on the publicFunctions object.
      if (publicFunctions.hasOwnProperty(functionName) && typeof func === "function") {
        ProxyClass.prototype[functionName] = createProxyFunction(functionName);
      }
    }

    return ProxyClass;
  }

  function copyToPrototype(source, destination) {
    var prototype = destination.prototype,
        property;
    for (property in source) {
      if (source.hasOwnProperty(property)) {
        prototype[property] = source[property];
      }
    }
  };

  function createRealClass(constructor, publics, privates, proxyClass) {
    var RealClass = function() {
        var proxy;

        if (typeof constructor === "function") {
          // Call the constructor function to perform any initialization of the object.
          constructor.apply(this, arguments);
        }
        proxy = new proxyClass(this);
        // Maintain the illusion that the proxy object is a real object.
        // Assign the constructor property in case anyone uses it to create another instance.
        proxy.constructor = RealClass;
        // Returning the proxy object means creating a new instance of Class
        // results in a proxy object, instead of the real object.
        // Callers can then only interact with the proxy.
        return proxy;
        };
    // The RealClass has both public and private functions.
    copyToPrototype(publics || {}, RealClass);
    copyToPrototype(privates || {}, RealClass);

    return RealClass;
  }

  // Return the defineClass function.
  return function(options) {
    // 'public' and 'private' are reserved keywords, so the option properties must be
    // accessed using strings instead of options.public, for example.
    var proxyClass = createProxyClass(options["public"]),
        realClass = createRealClass(
      options["constructor"], options["public"], options["private"], proxyClass);
    return realClass;
  };

}());

var Customer = defineClass({
  "constructor": function(id) {
    this.id = id;
    this.totalSpend = 0;
  },
  "public": {
    placeOrder: function(order) {
      this.totalSpend += order.total;
    },
    getReward: function() {
      if (this.isSpecial()) {
        return "Special Customer Coupon!";
      } else {
        return "Nothing Today";
      }
    },
    toString: function() {
      return "Customer #" + this.id;
    }
  },
  "private": {
    isSpecial: function() {
      return this.totalSpend > 100;
    }
  }
});

var customer = new Customer(123);
customer.toString(); // > "Customer #123"
customer.placeOrder({
  total: 10
});
customer.getReward(); // > "Nothing Today"
customer.placeOrder({
  total: 101
});
customer.getReward(); // > "Special Customer Coupon!"
//var customer = new Customer(123);
customer.totalSpend = 1000;
customer.getReward(); // > "Nothing Today"
typeof customer.isSpecial; // > "undefined"
//////////////////////////////////////////////////////
pending…
Crockford's metnod
function Doctor(name, specialty, sallary) {

  this.getName = function() {
    return name;
  }

  this.setName = function(value) {
    name = value;
  }
  this.getSpecialty = function() {
    return specialty;
  }
  this.setSpecialty = function(value) {
    specialty = value;
  }
  this.getSallary = function() {
    return sallary;
  }
  this.setSallary = function(value) {
    sallary = value;
  }
}
var manos = new Doctor("Manos", "Gynae", 10000);
manos.setSallary(300000);
manos.getName() + " " + manos.getSallary();

var panos = new Doctor("Pano", "xxx", 0);
panos.setName("Panos");
panos.setSpecialty("Mathematician");
panos.setSallary(10);
panos.getName() + " " + panos.getSallary() + " " + panos.getSpecialty();
manos.getName() + " " + manos.getSallary();
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment