10

I have been experimenting using static methods in Javascript. Instead of having objects inherit from a prototype, I use duck-typing a lot harder.

var Controller = {};
Controller.getData = function() {//return data};

// and then in use:
var page = route.getPage();
require([page], function(Controller) {
    Controller.getData();
});

I could do this same by creating new objects with the Controller prototype:

function Controller() {};
Controller.prototype.getData = function() {//return data};

// and then in use:
var page = route.getPage();
require([page], function(Controller) {
    var controller = new Controller();
    controller.getData();
});

My gut feeling is that the static method will be faster, but I have no clue. In general, what are the performance discrepancies between these two methods?

TLDR; basically this question but for Javascript.

Community
  • 1
  • 1
eatonphil
  • 13,115
  • 27
  • 76
  • 133
  • You should put up a test case at https://jsperf.com/ and test your assumptions (here: http://jsperf.com/static-vs-prototype-methods-test, difference looks marginal for the most basic of tests) – Rob M. May 22 '15 at 18:13
  • I would expect them to perform the same. There might be some weirdness about multiple levels of inheritance, where the prototype chain must be traversed (I'm unsure if JavaScript optimizes lookups). If you are placing something directly on the object you intend to use, I doubt there would be a difference. Honestly, it comes down to whether or not `getData` needs access to an instance of Controller. Like Rob says, give jsperf.com a try. It might be worth a test. – Trey Cordova May 22 '15 at 18:17
  • JavaScript does not support static methods - using prototype is the closest you will get to a static method. The question you have linked is for C# not JavaScript. – Y123 May 22 '15 at 18:18
  • @YazadKhambata Javascript (ES6) does support static methods (not overly useful unless you are using traceur or babel though) – Rob M. May 22 '15 at 18:19
  • 1
    @YazadKhambata no problem, I recommend looking at this post: http://www.2ality.com/2015/02/es6-classes-final.html – Rob M. May 22 '15 at 18:21
  • @RobM. - Thanks again - I will have a look! – Y123 May 22 '15 at 21:43

1 Answers1

5

Edit: So there is a bit of a performance difference when you are instantiating the class vs. calling the "static" version, but the difference doesn't really warrant you making any changes to your code (premature optimization) unless you are seeing an actual slow down.

As demonstrated in the basic jsperf test I setup, there really isn't much of a difference, performance wise. You should make the decision based on whether or not you want the context (this) to refer to your base class or not.

Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • I updated your test a little bit with what I think is more relevant. Does this make sense to test this way? This is more what I had in mind. And there seems to be a more significant difference. http://jsperf.com/static-vs-prototype-methods-test/2 – eatonphil May 22 '15 at 18:25
  • @eatonphil Thanks! I was actually just doing the same thing, I'll update the answer – Rob M. May 22 '15 at 18:26
  • There is a significant difference on firefox for me, but on chrome they are pretty much equal. Do you still feel like this is a good test? Can I extrapolate meaningfully from these tests for performance (just on firefox, I guess)? – eatonphil May 22 '15 at 18:26
  • The prototype is a little slower, with chained prototypes, it could get even slower. However, you are right that the performance is not really relevant and the decision should be based on whether the OP needs a static or an instance method. They question is really misguided. – Ruan Mendes May 22 '15 at 18:27
  • @JuanMendes why is this necessarily misguided? Can't I take from this that if I were doing heavy computation in Javascript, I might be better off not encapsulating objects in the (most common) prototypal method as opposed to using "static" objects that have no prototypal chain. Am I wrong for making this connection? – eatonphil May 22 '15 at 18:29
  • 2
    @eatonphil I updated my answer, you are still getting 33 million operations per second vs 43M using the static method. Unless you are doing some absolutely incredible volume that requires 45M operations per second, this falls in the realm of premature optimization – Rob M. May 22 '15 at 18:31
  • @RobM. Haha that is a good point. I am writing a blog post about writing OCaml-style Javascript code. I decided to look into if there were actually any performance differences between using prototypal object and not. Thanks for all the help though. – eatonphil May 22 '15 at 18:32
  • @eatonphil If you need access to instance properties, you have to use an instance method. You cannot fake instance methods with static methods, unless you really hack around (passing the instance as the first parameter to every method). This is the classic case of trying to do premature optimization. A static method is just a global method, and instance method acts on an instance. – Ruan Mendes May 22 '15 at 18:34
  • @eatonphil My pleasure, it's good to pose ivory tower questions like this, hopefully you can utilize jsperf.com or a similar service to help you get performance data in the future. – Rob M. May 22 '15 at 18:34
  • @JuanMendes what is a hack in one language may be the modus operandi in another (OCaml, here for instance). That said, I do not think it is always necessary to create instances when I do not need them. In general, I see no reason why my controller warrants an instance. It is responsible for two methods: get the data and execute a callback once the data has been put in place. Even if there are multiple controllers for multiple routes, they do not conflict and I have no need for instance data. It can be stored on the object itself. This is surely not the only area this method may be useful. – eatonphil May 22 '15 at 18:38
  • @eatonphil My point is that it's very unlikely to cause a performance problem unless it's in a tight loop. Don't fix it until it's broke, and don't go against the facilities the language provides you, or other developers that touch your code will hate you when trying to read your code. Don't make your code harder to read unless you know you have a performance bottleneck. For what it's worth, I thought that the hit would be with inherited methods because it has to look up the prototype chain, but it doesn't seem to be the case, http://jsperf.com/static-vs-prototype-methods-test/3 – Ruan Mendes May 22 '15 at 18:42
  • This is also a good case against not using prototype methods. Though I cannot quite say I understand why. http://jsperf.com/static-vs-prototypal-objects/2 – eatonphil May 22 '15 at 19:18
  • @eatonphil There was an error in that test case (the static method was checking `a > this.value` which would always return false and thus skip an insert. Here is the fixed test case with much less difference in performance: http://jsperf.com/static-vs-prototypal-objects/3 – Rob M. May 22 '15 at 19:22
  • 2
    All the tests are misleading. The static version is faster only because you instantiate an object on the heap each time (causing allocation and GC stress). The invocations themselves don't have any substantial difference. The initial question itself is wrong. Static vs prototype functions are the same in matter of performance (prototype is even faster because it generally leverage JIT optimizations). That said, the choice should be made for design purpose, not for eager optimization. – ngryman Apr 25 '17 at 23:28