jeudi, septembre 11, 2008

Javascript: The Black Beast of Aaaaarrrrgggghhhh (part 3)

With this third part, we're starting to dig into the interesting bits: modules or how to manage the scope of your code.
EDIT: Modules are delayed to a further blog post :p

But before this, let's talk about something else as an appetizer.

Boolean(false) is truthy

Javascript shares the burden of C-Style truthy/falsy concept. These are non-boolean expressions that can be treated as a boolean value. It is both powerful and very dangerous, because (once again) it presumes the developer already knows everything about the language's subtleties.

So let's first list the falsy elements, all the rest being truthy: 0,false (of course), empty string: "" or '', null

Presented this way, it seems quite simple... though there are some quirks due to where and how you're going to take advantage of these evaluations.
For example, 0 evaluates to false, while '0' evaluates to true (non-empty string). This sounds easy once again, but can be tricky when you receive a variable value and just test it this way: if(myVar){...}. It can lead to very counter-intuitive tests...

var myVar=new Boolean(false);
if(myVar){
    alert("true");
// Never use alert() in real applications, it blocks all javascript execution in all tabs of a browser until you close it.
}
This is one example of code where one should stop thinking in another language's logic (Java or C# for example). new Boolean(false) is an object, and an object is always truthy, ending up with an alert popup showing "true".
Though if you replace if(myVar)... with if(myVar==true)... the test will end up as expected, with nothing happening.
This can be confusing... I agree, and it did confuse me. Until I heard about the === operator. In javascript, == was designed as a tolerant operator, which accepts 1=='1' as a true assertion. So in later versions of javascript (when war between Netscape and IE was raging a while ago), a new === operator was introduced for a comparison of references. This operator is the one you'd want to use in order to be sure that an object is the same as another.


Oh and by the way, this may not be the last of my posts about javascript... so I'm going to drop in some of the references I used, in order not to forget them, and leave you my dear only reader with something else to read ;).

a Blog post about Truthy falsy
The source of all javascript wisdom ;): Sir Crockford.

mardi, septembre 09, 2008

Javascript: The Black Beast of Aaaaarrrrgggghhhh (part 2)

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 do

When 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 ;).