Closure Versus Prototypal Object Creation

I was just looking through a new blog post from Brendan Eich over on
AMinuteWithBrendan where he went into some detail on Closures versus
Prototypal Patterns
.

After listening to his pod cast, (you can find the transcript here), I decided to put
the two patterns to test. So I fired up a new test on JSPerf.com

Setting up the Closure Pattern


function ClosurePattern() {
this.someMethod = function someMethod() {
console.log('foo');
}
}

Setting up the Prototypal Pattern


function PrototypalPattern() {}
PrototypalPattern.prototype = {
someMethod: function() {
console.log('foo');
}
}

Setting up the Prototypal Hoisting Pattern


function sm() {
console.log("foo")
}

function PrototypalWithHoisting() {}
PrototypalWithHoisting.prototype = {
someMethod: sm
}

Results

Closure Pattern

Closure Pattern

The closure pattern is quick in Chrome, but not nearly as fast in all the other browsers.

Prototypal Versus Hoisting

Prototypal Versus Hoisting

Prototypal and hoisting run neck and neck in all browsers, with Prototypal winning out in Chrome.

Closure Versus Prototypal

Closure Versus Prototypal

Here we are can start to se the overall winner in object creation.

Closure, Prototypal, Hoisting

Closure, Prototypal, Hoisting

I threw this one up here so you can see all 3 types next to each other.

Conclusion

After look at this set of test, I really think it all depends on your use case. While the Closure Pattern lends itself to
readability and the ability to have both public and private variables as well as public and private methods, object creation is
much slower. Also, as Brendan points out, you aren’t getting the same functionality as creating an object via the Prototypal Pattern.

The closure pattern, the one where you have the method as a function expression inside the constructor, can actually be more
expensive. If you think about it, each time you call that constructor (let’s say you call it a million times), you have to
evaluate the method function expression. You have to evaluate the assignment “this.someMethod = function() { /*etc*/ }”. In
JavaScript, every time you evaluate a function expression, you get a new object. You can tell it’s a new object because
of “===”; you can also mutate it: it’s mutable. So you can set a certain property on it that would not show up on any other
instances — “someMethod”. You’d say “new ClosurePattern()” and assign that to x, and also set y to “new ClosurePattern()”.
Now you’ve got two instances. x.someMethod !== y.someMethod, and “x.someMethod.foo = 42” would not cause 42 to appear on
y.someMethod: they’d be different objects. That hurts! If you do a million constructions, you’ve got not just a million
instances of the ClosurePattern object, you’ve got a million “someMethod”s inside it.

Unless I was creating an application that requires creating millions of JavaScript objects, I would still recommend the Closure
Pattern for code re-use.

3 thoughts on “Closure Versus Prototypal Object Creation”

    1. So you can still inherit using the prototypal pattern even with closures. It just takes a bit more work. However the trade off for readability may be worth it.



      // just make this a bit easier rather than a helper function.
      Function.prototype.inheritsFrom = function( parentClassOrObject ){
      if ( parentClassOrObject.constructor == Function )
      {
      //Normal Inheritance
      this.prototype = new parentClassOrObject;
      this.prototype.constructor = this;
      this.prototype.parent = parentClassOrObject.prototype;
      }
      else
      {
      //Pure Virtual Inheritance
      this.prototype = parentClassOrObject;
      this.prototype.constructor = this;
      this.prototype.parent = parentClassOrObject;
      }
      return this;
      }


      function ClosurePattern() {
      this.someMethod = function someMethod() {
      console.log('foo');
      }
      }


      function inheritClass() {
      this.otherMethod = function otherMethod() {
      console.log("bar");
      }
      }
      inheritClass.inheritsFrom(ClosurePattern);


      // new class
      var temp = new inheritClass();
      temp.someMethod(); // outputs "foo"
      temp.otherMethod(); // outputs "bar"

      Of course, syntax highlighting on this page may make it a bit worse!

Leave a Reply to Осмотр автомобиля перед покупкой Cancel reply

Your email address will not be published. Required fields are marked *