First part of this "series" introduced basic concepts of the javascript language.
This new entry will introduce the functional nature of javascript.
In javascript, there is (almost) no limit to where a function can be defined (as opposed to a class language like java for example). It doesn't even have to have a name and can be defined anonymously. A function can also be created as a local variable in another function's body (inner function).
Functions represent the real power of javascript. Not understanding them means not understanding javascript.
Javascript uses functions all around. Functions are
objects, and as such can be passed as parameters to other functions, or returned from other function's invocation.
As there is no proper class, one may think that there is no such thing as a method. This is not really the case. In fact one may call "method" any function defined as an attribute to an object.
var myObj={
myAttribute:"valueOfAttribute",
myMethod: function(){
if(console){
console.log("hello universe");
}
}
};
Functions are (almost) always stored in a variable of some kind, and can even be stored in local variables.
In fact, defining a function in an html script tag like this:
function myFunction(){
if(console){
console.log("hello universe");
}
}
... is completely equivalent to the following definition:
var myFunction=function(){
if(console){
console.log("hello universe");
}
};
This form is much clearer, as there is now no ambiguity about its object nature and about where it is stored... at least when you understand another little thing...
The global object:
In javascript, if you don't use the var keyword, or if you define variables in no specific construct (e.g. not in a function, an object, an array, or any conditional construct like if, for...etc),
variables are defined as attributes to the global object. The global object depends on the runtime you are coding for. In a browser, this global object is the window object.Now read my lips:
"GLOBAL OBJECT IS EVIL". This global space is the worst place for the definition of your code. Oh, and by the way, variables defined without the var keyword are
always defined as attributes of this global object, regardless of their scope.
So, what's the solution to this?
Create your own
namespace!
You'll often ear about namespaces in the javascript world. In fact, this just refers to a container (javascript object) containing all the objects, states and functions needed for your code. This allows you not to pollute the global namespace (though this is not sufficient to disallow access to private states, wait for 3rd part of this blog series on the module pattern).
YahooUI started this trend with the YAHOO namespace. Other frameworks have also created their namespace(s) (Ext.* for ExtJS, dojo.* for Dojo, a global "$" or "jQuery" object for JQuery, Prototype.* for prototype, etc...). This allows the use of various "libraries" that are less likely to collide, or at least in a more controlled fashion.
As demonstrated in previous blog entry, creating an object, and therefore a namespace, is very easy:
var MyNamespace={};
And now adding elements to this namespace is as easy as invoking
MyNamespace.myElement="element's value";
MyNamespace.myFunction=function(){
if(console){
console.log("hello universe");
}
}
You can see that the function we mentionned before is now defined in a custom object (namespace) and that we can therefore invoke:
MyNamespace.myFunction();
This exemple is of course very simplistic, and not very secure. In fact any code can replace these states, because objects don't have scopes! Let's detail this mind-boggling fact.
Objects don't have scopes, functions doWhen you create an object, its state is public and accessible to any code that has access to the object in the first place. Any other code can add, remove and update entries from this container.
The only mean of reducing scope in javascript is functions. Hence the functional nature of the language.
Whatever is defined in a function is only accessible to this function and to any other construct defined in this function.
The only visible thing from a given function, is the result from its invocation.
var myFunction=function(){
var myVar="hello universe";
// let's create an object accessing this 'private' state
var result={
myPublicVar:myVar+", I'm a public variable"
};
return result;
}
// next line will output undefined, because myVar is local to the function only.
console.log(myFunction.myVar);
// the next one will output 'hello universe, I'm a public variable', because the object returned by the invocation has access to the context of the function it was defined in (by the way, this is what is usually called access through a closure).
console.log(myFunction().myPublicVar);
As you may have noticed, and as a little conclusion to this post, one thing you really have to be careful with when reading or writing javascript code, is the presence of
(). Whether a function is invoked or not is really important. This will determine whether you are left with the function object itself, ready to be invoked at will, or with the result from this function's invocation.
This is it for the moment. next entry will deal with the constructors (and the other ways to invoke a function), the concept of module, the truthy/falsy idea, and also give credit to the reference(s) used to build this little introduction to javascript ;).