1

I am trying to understand difference between Prototype functions and nested functions. I Need to know the following

  1. Which is better , performance wise
  2. What is the main difference between the two
  3. Which structure is better suited for which situations (I assume both have different aim) ?

My Basic usage : My basic usage is I want to write a a main function for web app that when initiated, it will created menus, buttons , button clicks events, draw charts,make tables etc. during app navigation and i need my code to be structured in a better and fastest way. And I will be using jquery and its plugins alot *.

For simplicity of usage , consider I need to create portlets/widget container at many places/stages in may app, and I would just call var port = App.creatPortlet() and then port.content(// place data)

Kindly Help.

Performance: I created performance test here prototype-vs-nested-function and it seems PROTOTYPE function is faster. But I need some advice on it.

PROTOTYPE FUNCTION:

  function Person(opt) {
    this.firstName = opt.firstName;
    this.lastName = opt.lastName;
  }

  Person.prototype.getFullName = function() {
    return this.firstName + " " + this.lastName;
  };
 // Testing performance
 var P1 = new Person({
   firstName: 'Jeremy',
   lastName: 'McPeak'
 }).getFullName();

NESTED FUNCTION:

var Person = function(opt) {
   return {
     getFullName: function() {
       return opt.firstName + " " + opt.lastName;
     }
   };
 }
 // Testing performance
 var P1 = new Person({
   firstName: 'Jeremy',
   lastName: 'McPeak'
 }).getFullName();

UPDATE: http://jsperf.com/closure-prototype-static-reveal I created benchamrk according to my exact need.

1 Answer 1

3

Well first of all performance tests for such small portions of code are not really useful because you don't know if this will reflect the performance in real use case scenario. (It could happen that you test the optimizer of the JS engine for that small code, e.g. inlining of some methods or that you trigger an optimizing process of the JS engine that would take longer to initialize but would bring performance boosts in realtime applications, that you detected a flaw of the testing library, ....)

I bet you don't test prototype vs nested functions here but two assignments vs scope handling.

Looking at your test, you don't even test both cases. You just test the case two (In your preparation you overwrite the access to the name function Person with the var Person = ...;, so function Person is never used in your test). It should look like this: updated jsperf.com.
(EDIT looks like you already changed yourself while i was writing).

Anyway what is the difference and what is better. Well both have valid use cases and it is up to you to determine what is better.

Object Type

For the first one, every object created by Person is of the same type:

 var p1 = new Person();
 var p2 = new Person();

 console.log( p1 instanceof Person);  //true
 console.log( p2 instanceof Person);  //true

While with the second example every object you create is of type Object.
So with he first one you, if the object is passed to another function, you can test if it is of type Person, while for the second one you can't.

While I prefer to test for the existence of a feature/function instead of testing for a type, this would - for me - make no difference.

Prototype chain

Sometimes it is useful to updated/extend functionality for all objects or modify/extend an existing function for all objects of one type.
While this is possible for the first Example it is not possible for the second one.

var Person = function() {
};

var p1 = new Person();
Person.prototype.doSomething = function() {console.log("....");};

p1.doSomething();

Reuse of code

With the first example you can reuse your functions on objects that are similar to the given one. You could do something like this:

Person.prototype.doSomething.call(similarOBject, ...);

Which could be handy in some situations. An example where this is often use are Array functions on array like objects.

Protection of raw data

Sometimes it is useful to protect some raw data from being read/modified directly. That is that is strength of the second example. While I personally thing this should be handled by a good documentation instead of forcing it by code it is still a valid use case. In your example firstName and lastName is completely hidden from outside, except for the code part that creates the the Person.

Performance and Speed

Which one performs better in speed and memory usage depends mainly on the JS engine. Not every engine will create a new function for the nested functions, it is more likely that it is correctly detected and just references on the second call. The scope creation will have some overhead, but this is probably negligible depending on the object count and how frequent you create them.

But as already said you will most likely have other things in your code that will create bottlenecks.

In most of the cases using prototype is the better choice with of respect maintainability and readability.

Sign up to request clarification or add additional context in comments.

7 Comments

I modified the test above. Prototype seems faster.
(1). Can you kindly update article based on memory usage of both cases ? (2). Can i encapsulate protoype fucntions ? so I keep person`s module and its vars private ? Kindly provide example ?
@django You don't only test prototype vs nested functions but also assignment vs scope creation. Thats one point why your test is not really useful, and the other one is that is way of testing does not reflect a real scenario. Js engines have many optimization/analyzation steps. Anyway most of libraries use prototype for most of the parts of their library. This is a better indication then the performance test.
@django Memory usage and performance depends on the implementation of the various js engines. While your nested functions would have a reference for each function you want to have for the object and a scope bound to each of these (for the obj) this most likely would use more memory and performance, then the prototype base example where you just have a reference_/_information entry for the prototype chain.
@django Without creating a closure in the constructor, by creating a function inside of it and assigning it to the created object, you can't create private members. Most of the time it is a better choice in js to mark them private (e.g. by prepending a _ to the name and adding e.g. some jsdoc comment) instead of using such workarounds. Coming from languages that support the protected and private I also tried to solve this missing feature, but in the end this brings more problems then it solves (the are some little exceptions but not many).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.