Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript prototype operator performance: saves memory, but is it faster?

I read here (Douglas Crockford) using prototype operator to add methods to Javascript classes saves also memory.

Then I read in this John Resig's article "Instantiating a function with a bunch of prototype properties is very, very, fast", but is he talking about using prototype in the standard way, or is he talking about his specific example in his article?

For example, is creating this object:

function Class1() {    this.showMsg = function(string) { alert(string); } } var c = new Class1(); c.showMsg(); 

slower than creating this object, then?

function Class1() {} Class1.prototype.showMsg = function(string) { alert(string); } var c = new Class1(); c.showMsg(); 

P.S.

I know prototype is used to create inheritance and singleton object etc. But this question does not have anyhting to do with these subjects.


EDIT: to whom it might be interested also in performance comparison between a JS object and a JS static objet can read this answer below. Static object are definitely faster, obviously they can be usued only when you don't need more than one instance of the object.

like image 786
Marco Demaio Avatar asked Aug 16 '10 12:08

Marco Demaio


People also ask

Does prototype improve memory optimization?

'Prototype' helps remove code redundancy which helps boost your app's performance. If you are seeking to optimize resources or memory on your application, you should use prototype . Declaring this in your constructor can cause object redundancy, especially when the properties are methods.

What is the advantage of prototype in JavaScript?

Prototypes allow you to easily define methods to all instances of a particular object. The beauty is that the method is applied to the prototype, so it is only stored in the memory once, but every instance of the object has access to it.

Should you use prototype in JavaScript?

There is a clear reason why you should use prototypes when creating classes in JavaScript. They use less memory. When a method is defined using this. methodName a new copy is created every time a new object is instantiated.


2 Answers

Edit in 2021:

This question was asked in 2010 when class was not available in JS. Nowadays, class has been so optimized that there is no excuse not to use it. If you need to use new, use class. But back in 2010 you had two options when binding methods to their object constructors -- one was to bind functions inside the function constructor using this and the other was to bind them outside the constructor using prototype. @MarcoDemaio's question has very concise examples. When class was added to JS, early implementations were close in performance, but usually slower. That's not remotely true anymore. Just use class. I can think of no reason to use prototype today.


It was an interesting question, so I ran some very simple tests (I should have restarted my browsers to clear out the memory, but I didn't; take this for what it's worth). It looks like at least on Safari and Firefox, prototype runs significantly faster [edit: not 20x as stated earlier]. I'm sure a real-world test with fully-featured objects would be a better comparison. The code I ran was this (I ran the tests several times, separately):

var X,Y, x,y, i, intNow;  X = function() {}; X.prototype.message = function(s) { var mymessage = s + "";} X.prototype.addition = function(i,j) { return (i *2 + j * 2) / 2; }  Y = function() {   this.message = function(s) { var mymessage = s + "";}   this.addition = function(i,j) { return (i *2 + j * 2) / 2; } };   intNow = (new Date()).getTime(); for (i = 0; i < 10000000; i++) {   y = new Y();   y.message('hi');   y.addition(i,2) } console.log((new Date()).getTime() - intNow); //FF=5206ms; Safari=1554  intNow = (new Date()).getTime(); for (i = 0; i < 10000000; i++) {   x = new X();   x.message('hi');   x.addition(i,2) } console.log((new Date()).getTime() - intNow);//FF=3894ms;Safari=606

It's a real shame, because I really hate using prototype. I like my object code to be self-encapsulated, and not allowed to drift. I guess when speed matters, though, I don't have a choice. Darn.

[Edit] Many thanks to @Kevin who pointed out my previous code was wrong, giving a huge boost to the reported speed of the prototype method. After fixing, prototype is still around significantly faster, but the difference is not as enormous.

like image 107
Andrew Avatar answered Sep 26 '22 02:09

Andrew


I would guess that it depends on the type of object you want to create. I ran a similar test as Andrew, but with a static object, and the static object won hands down. Here's the test:

var X, Y, Z, x, y, z;  X = function() {}; X.prototype.message = function(s) {   var mymessage = s + ""; } X.prototype.addition = function(i, j) {   return (i * 2 + j * 2) / 2; }  Y = function() {   this.message = function(s) {     var mymessage = s + "";   }   this.addition = function(i, j) {     return (i * 2 + j * 2) / 2;   } };  Z = {   message: function(s) {     var mymessage = s + "";   },   addition: function(i, j) {     return (i * 2 + j * 2) / 2;   } }  function TestPerformance() {   var closureStartDateTime = new Date();   for (var i = 0; i < 100000; i++) {     y = new Y();     y.message('hi');     y.addition(i, 2);   }   var closureEndDateTime = new Date();    var prototypeStartDateTime = new Date();   for (var i = 0; i < 100000; i++) {     x = new X();     x.message('hi');     x.addition(i, 2);   }   var prototypeEndDateTime = new Date();    var staticObjectStartDateTime = new Date();   for (var i = 0; i < 100000; i++) {     z = Z; // obviously you don't really need this     z.message('hi');     z.addition(i, 2);   }   var staticObjectEndDateTime = new Date();   var closureTime = closureEndDateTime.getTime() - closureStartDateTime.getTime();   var prototypeTime = prototypeEndDateTime.getTime() - prototypeStartDateTime.getTime();   var staticTime = staticObjectEndDateTime.getTime() - staticObjectStartDateTime.getTime();   console.log("Closure time: " + closureTime + ", prototype time: " + prototypeTime + ", static object time: " + staticTime); }  TestPerformance();

This test is a modification of code I found at:

Link

Results:

IE6: closure time: 1062, prototype time: 766, static object time: 406

IE8: closure time: 781, prototype time: 406, static object time: 188

FF: closure time: 233, prototype time: 141, static object time: 94

Safari: closure time: 152, prototype time: 12, static object time: 6

Chrome: closure time: 13, prototype time: 8, static object time: 3

The lesson learned is that if you DON'T have a need to instantiate many different objects from the same class, then creating it as a static object wins hands down. So think carefully about what kind of class you really need.

like image 28
shmuel613 Avatar answered Sep 26 '22 02:09

shmuel613