Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OO Javascript constructor pattern: neo-classical vs prototypal

I watched a talk by Douglas Crockford on the good parts in Javascript and my eyes were opened. At one point he said, something like, "Javascript is the only language where good programmers believe they can use it effectively, without learning it." Then I realized, I am that guy.

In that talk, he made some statements that for me, were pretty surprising and insightful. For example, JavaScript is the most important programming language on the planet. Or it is the most popular language on the planet. And, that it is broken in many serious ways.

The most surprising statement he made, for me, was "new is dangerous". He doesn't use it any more. He doesn't use this either.

He presented an interesting pattern for a constructor in Javascript, one that allows for private and public member variables, and relies on neither new, nor this. It looks like this:

// neo-classical constructor var container =  function(initialParam) {     var instance = {}; // empty object       // private members     var privateField_Value = 0;     var privateField_Name = "default";      var privateMethod_M1 = function (a,b,c) {         // arbitrary     };       // initialParam is optional     if (typeof initialParam !== "undefined") {         privateField_Name= initialParam;     }      // public members     instance.publicMethod = function(a, b, c) {         // because of closures,         // can call private methods or         // access private fields here.      };      instance.setValue = function(v) {         privateField_Value = v;     };      instance.toString = function(){         return "container(v='" + privateField_Value + "', n='" + privateField_Name + "')";     };      return instance; }   // usage var a = container("Wallaby"); WScript.echo(a.toString());  a.setValue(42); WScript.echo(a.toString());   var b = container(); WScript.echo(b.toString());  

EDIT: code updated to switch to lowercase class name.

This pattern has evolved from Crockford's earlier usage models.

Question: Do you use this kind of constructor pattern? Do you find it understandable? Do you have a better one?

like image 676
Cheeso Avatar asked Nov 27 '09 17:11

Cheeso


People also ask

What is the difference between prototypal and classical inheritance?

Classical inheritance is limited to classes inheriting from other classes. However prototypal inheritance includes not only prototypes inheriting from other prototypes but also objects inheriting from prototypes.

What is prototypal inheritance in JavaScript?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object.

What kind of inheritance mechanism is used in JavaScript?

Inheritance is an important concept in object oriented programming. In the classical inheritance, methods from base class get copied into derived class. In JavaScript, inheritance is supported by using prototype object. Some people call it "Prototypal Inheriatance" and some people call it "Behaviour Delegation".

Does JavaScript support class like inheritance?

JavaScript supports inheritance if you use it. Look up "JavaScript prototype chain". As for "Why javascript does not support classical inheritance as a default option?" - because that's how JavaScript was defined.


1 Answers

This looks like the non-singleton version of the module pattern, whereby private variables can be simulated by taking advantage of JavaScript's "closures".

I like it (kinda...). But I don't really see the advantage in private variables done in this way, especially when it means that any new methods added (after initialisation) do not have access to the private variables.

Plus, it doesn't take advantage of JavaScript's prototypal model. All your methods and properties must be initialised EVERY time the constructor is called - this doesn't happen if you have methods stored in the constructor's prototype. The fact is, using the conventional constructor/prototype pattern is much faster! Do you really think private variables make the performance hit worth it?

This kind of model makes sense with the module pattern because it's only being initialised once (to create a pseudo-singleton), but I'm not so sure it makes sense here.

Do you use this kind of constructor pattern?

No, although I do use its singleton variant, the module pattern...

Do you find it understandable?

Yes, it's readable and quite clear, but I don't like the idea of lumping everything inside a constructor like that.

Do you have a better one?

If you really need private variables, then stick with it by all means. Otherwise just use the conventional constructor/prototype pattern (unless you share Crockford's fear of the new/this combo):

function Constructor(foo) {     this.foo = foo;     // ... }  Constructor.prototype.method = function() { }; 

Other similar questions relating to Doug's views on the topic:

  • Pseudo-classical vs. “The JavaScript way”
  • Is JavaScript ‘s “new” Keyword Considered Harmful?
like image 179
James Avatar answered Oct 14 '22 09:10

James