Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to introduce the prototype pattern to javascript namespace

Before I begin, I want to confess that I am a JavaScript novice and I have very little understanding/knowledge of JavaScript patterns and terminologies so please feel free to explain basic concepts to me like I'm 5!

I have previously used the JavaScript prototype pattern to great effect in my work.

Here is a sample of my previous work with the prototype pattern

var SomeNameSpace = SomeNameSpace || {};
SomeNameSpace.SomeClass = function(oSomeParameter){
     this.SomeProperty = oSomeParameter
     ...
}

SomeNameSpace.SomeClass.prototype = {
     SomeClassMethod: function (oSomeOtherParameter) {//code here}
}

var someClassInstance = new SomeNameSpace.SomeClass("some string");
var result = someClassInstance.SomeClassMethod("some other string");

That snippet is an example of how I have always worked with javascript

I have been put in charge of supporting some new javascript code. I would like to introduce the same sort of prototype pattern to this new library. However, the namespace is written in a way which is foreign to me and I do not know how to modify it to suit my needs.

An example

if (typeof SomeNamespace == "undefined") {
    SomeNamespace = { __namespace: true };
}



 SomeNamespace.SomeOtherNamespace = {
     SomeClass: function(oSomeParameter){
          this.SomeProperty = oSomeParameter
          ...
     }
 }

I don't know how to add prototype functions to this code....

(Sorry if I'm vague on details, I'm not even sure why the namespace is declared like that in my 2nd example so if someone could explain that to me, that'd be great!)

*Edit* Corrected syntax in 2nd example

*Edit* Left out the "new" keyword in my example

like image 940
user2727893 Avatar asked Feb 16 '23 04:02

user2727893


1 Answers

Defining methods

This piece of code is not syntactically correct:

SomeNamespace.SomeOtherNamespace = {
     SomeClass = function(oSomeParameter){  // you probably have : instead of =
          this.SomeProperty = oSomeParameter
          ...
     }
 }

To add an instance method in the second example, you can simply do after the definition of SomeClass:

SomeNamespace.SomeotherNamespace.SomeClass.prototype.SomeClassMethod = function() {
};

In both the first and the second way you mentioned, your code wants to show that these functions (instance methods in first example, classes in second example) all belong to the same object (prototype in first example, namespace in second example). That is all nice and good for a few properties, but i find this gets more in the way when you're dealing with classes with many methods or even worse, namespaces with many classes.

I would recomend you separate your code using different files and minify them together. A folder represents a namespace and a file represents a class. Follow the pattern in your first example, but instead of saying "this is the prototype object with these methods", simply add them one at a time using the example line above.

Declaring namespaces

First of all, we need to be on the same page. In JavaScript a namespace is simply an object (that contains as properties whatever interests you, constructors, static functions - ex factory methods, other namespaces, etc).

The first example a = a || {} makes sure that namespace a is defined but makes sure not to overwrite it if it was defined elsewhere. For most use cases it is enough and it has the advantage of being very concise and clear to most people reading your code.

The second example does something similar to what the first does, but with two differences:

  1. Specifically checks that a was undefined before defining it (ex1 only checked for falsyness which is usually enough)
  2. Adds the _namespace property to a

Regarding the check for undefined, i doubt you need it. If your code has collisions with something that uses 'a' as something else than an object, then there's a high chance something will break regardless of the method used.

The _namespace property is something purely conventional to that code i think. It may help with various tools (perhaps during debugging or for automatic documentation generation), but that's about all i can think of. Obviously you're in a much better position to see if it is actually used for something, so if you encounter an interesting usage, perhaps you could leave a comment.

To sum it up, i prefer the first variant because it is more concise and even more frequent (so easier to recognize by someone reading the code).

Full example:

// class definition
a = a || {}; // global namespace, all good
a.b = a.b || {}; // both lines are needed

a.b.Class = function() {
  this.myProp = 'hello';
};

a.b.Class.prototype.myMethod = function() {
};


// usage
var myInstance = new a.b.Class();
instance.myMethod();
var x = instance.myProp;
like image 110
Tibos Avatar answered Apr 30 '23 16:04

Tibos