In this article I will discuss one of the development pattern for creating JavaScript functions, Object Literal notation. We will look at the advantages to doing so and look at some of the neat things we can get from eclipse using this development pattern.
Introduction
As I have discussed on multiple occasions in blog posts and webinars, you should always try and separate your client side JavaScript from your XPages as much as possible. Using JavaScript libraries has many advantages:
- Changes can be made without building your XPages
- Separation of and therefore increased maintainability of functional design elements
- Debugging using browser development tools
- Syntax highlighting in the eclipse JavaScript editor
Creating JavaScript functions
There are many way in which you can create functions in JavaScript. You should definitely read this article Essential JavaScript Namespacing Patterns. Generally though the most common pattern I have come across in Domino development is the basic:
function foo(){ // Do some stuff }
As Domino developers, historically, JavaScript has been one of the languages we use to develop the application but “we” have never thought of ourselves as “JavaScript developers”, so why should we worry about doing it right, as long as it works….. But times changed quite some time ago and being a web developer is no longer about creating an application which works on the web, it is about using the web based tools and languages to the fullest of their potential. Domino Designer in Eclipse is not just our server side development environment, it is a powerful web based application development environment…..
Namespacing
In the browser the global (unspoken) namespace is “window” and any function created in this basic manner is created at that level. Any global variables declared at this level are pervasive across your application web page instance. For Example:
bar = [1] function foo(bar){ //Do something to bar } foo(bar);
is the same as writing
window.bar = [1] window.foo = function(bar){ //Do something to bar } window.foo(bar);
Polluting the namespace
What does that mean? If you have two variables or functions called the same thing then you can have conflict, pain and suffering. This can be caused by having multiple developers working on the same application and two of them using the same name for a function in a separate library they are working on, and then when the project is put together we have a problem.
Object Literal Notation
Creating a object from a literal array is simple in Javascript. “Object literal notation can be thought of as an object containing a collection of key:value pairs with a colon separating each pair of keys and values.”
This code creates a global person object with a firstname and lastname string property, and the age number property. The person object in in the global namespace but everything within the object is not. In this way we have taken up one global variable and not 4 (potentially):
var person = { firstname: 'marky', lastname: 'roden', age: 21 }
The typeof each property is not restricted to string and numbers – you can also have functions. In this example the fullname is returned from a function:
var person = { firstname: 'marky', lastname: 'roden', age: 21, fullname: function(){ return this.firstname + " "+this.lastname } } console.log(person.fullname())
Notice the use of “this” within the function. You have to be very careful when using “this” as a reference because of the JavaScript scoping but in this case it is straight forward. “this” is the person object.
So how does this help us write better JavaScript?
On occasions I have seen over 100 Javascript functions created within a single library, function after function after function. This makes for some tedious reading and maintainability is harder than it should be. When you see a function call on a web page which is causing you problems, you have no idea (without hunting for it) where the function is that you need to debug.
In addition as we have discussed if all the functions are at the top level within the namespace you have the risk of pollution and there is nothing more frustrating than staring at your correct looking function and wondering why it isn’t working, when in fact there is another function with the exact same name in the code you don’t know about. I expect many of you have been there, as have I.
Using the syntax as I demonstrated for person above we are able to create an object with a meaningful name and within that create functions.
So let’s plan to create our codebase with that premise….
For example I am now writing my grid functions to look like this:
var gridFunc = gridFunc || {} //if the object does not already exist declare it as an empty array gridFunc = { self: this, grid: function(){ return Ext.getCmp('myPanel') }, addLoading: function(){ //add a loading mask }, loadGrid: function(restService, titletag, query){ //load the grid } } //if I ever need to get a handle to the grid on the screen I would call var grid = gridFunc.grid() //and because it is returned as an EXTJS object I can then use it as I normally would a grid variable grid.doLayout(...)
Then we could create some chart functions like this
var chartFunc = chartFunc || {} chartFunc = { loadPieChart: function(someJSON){ //load a Pie Chart }, grid: function(name, color1, color2){ //load a grid Chart }, loadBarChart: function(xAxis, yAxis, someJSON){ //load a BarChart } }
As you can see both of these objects contain a “grid” function but they do not clash because they are referenced as two completely different items:
- chartFunc.grid()
- gridFunc.grid()
Some nice features of Domino Designer in Eclipse
DDE helps us with code assist when you start you write JavaScript using Object Literals. I first created a JavaScript library within my database. That automatically opens up in an eclipse “JavaScript” editor. You do not get this functionality through an XPage source as that is an XML editor.
When you write a function the “old way” there is no help when you start to write out your code:
But with object literal notation you get code assist. First of all it lists all the possible options for the demo object. If you have a list of functions within the object they will start to appear with the code assist. You’ve seen that before in DDE with other languages, now you’ve seen it in JavaScript as well !
The code assist shows us that person is typeOf array and accepts up to three parameters. We can think of this as a method of the Person object.
If we add a string to our object the code assist tells us so. We can think of this as a property of the Person object.
That makes for a much easier life when coding!
Maintainability
Although you can separate your code into separate .js files for each functional capability (e.g. graphs.js, charts.js) I believe that using the object literal notation can take that abstraction another step, making code easier to find.
When we start to abstract our JavaScript code like this we take the first steps towards adding “JavaScript” developer to our toolset as a Domino developer.
There are other tool which can be used to develop JavaScript code libraries (sublimeText for example) and these tools provide even greater control over well written code. Writing the code “right” the first time will have its advantages down the line.
Conclusion
There is much to talk about – go read this article 5 times – it will take that long to take in the first couple of patterns, then bookmark it and come back to learn more. There are better ways to program – learn them 🙂
Just went through a training course on patterns like this. They reviewed Module pattern, Revealing Module pattern, Prototype pattern and Revealing Prototype pattern. I haven’t had a chance to experiment with it yet.
I would love to see which you think is better for XPages development. I still don’t believe we are “JavaScript” developers and we are never going to create a library like EXTJS so how complex a pattern do we really need? thanks for taking the time to comment 🙂
Really tough to say at this point. All have their own pros and cons. At this point, it looks like Revealing Prototype would be best for building libraries of functions to use across multiple applications, especially if you wanted to extend them without having to change the function library, or for functions that are used to create multiple instances of the same type of object because the prototype code is only loaded once instead of once per instance. Revealing Module is also a good way to modularize the code and is easier to grasp than Revealing Prototype but isn’t extensible or as efficient with memory. That’s what I understand right now anyway.
Right – and if we were going to build a set of functions for an intranet built on Domino (or any other platform for that matter) that would make a lot of sense.
My feeling is that the bulk of heavy lifting is still done server-side and XPages actually promotes that, making it easier for developers to code SSJS rather than CSJS.
For every semicolon you skipped a kitted must die – besides that: nice article. I would post the link to the article about semicolons, but your plug-in won’t let me.
So google for inimino javascript_semicolons
Your namespacing section includes a hint of this, but there’s also such a thing as “array literal”. I see this ALL OVER THE PLACE:
var someListOfSomething = new Array();
Eww.
var someListOfSomething = [ ];
Better. Less typing, but also less side effects, because the Array constructor can do some funky stuff when called directly. So, similarly:
var someObject = new Object();
…should be:
var someObject = { };
But, as your article makes very clear, much (if not all) of an object or array’s definition really should just be specified in its initial construction, rather than creating a variable, and then mucking with its properties from outside of it after the fact.