Wednesday, April 18, 2012

Naked JavaScript - Function Basics

After talking about the basics of objects in the previous article, in part 2 of this series - Naked Javascript, we will discuss a little more about objects, their properties and take a sneak peak at functions in javascript.

As we learnt in the previous post, in Javascript you can create objects of the same class but each object can have a different set or properties. Properties can be defined on javascript objects even after they have been declared and used any number of times. For example, you can do this in javascript.

var bingo = {name:'xyz'};
bingo.says = 'hello';
bingo.volume = 5;


As you see, you can add properties to a javascript object even after the object has been declared and initialzied. This is something that cannot be done in Java because each object in Java MUST confirm to the structure of the class of which it is an instance. This feature of being able to dynamically create new properties for existing objects in javascript is called expandos.

If javascript allows you to create expando properties, it also lets you delete them dynamically. Here's how you would delete a property from a javascript object.

delete bingo.volume;


The above statement will delete the volume property on the bingo object thereby clearing the memory occpied by the object's value.

Not only can you declare properties on javascript objects, but you can also declare functions. It would'nt be too far fetched to say that functions are the actual building blocks of javascript.





Functions can be defined in Javascript in a couple of ways.

1) The not so cool way

function doSomethingCool(){
 console.log('I do something mindblowingly cool');
}


2) The cool way - Anonymous functions

function (){
 console.log('My parents forgot to name me!');
};


As you see, an anonymous function has no name(and hence the name 'anonymous' functions! Now that kinda reminds me of the saying - those that have nobody have god). There are many ways in which you can use anonymous functions. But before you start using functions - anonymous or non anonymous, you need to make a clear mental note of one point - Like everything else in javascript, functions are objects too! which means that you can assign it to a variable(huh?).

Lets try to build upon the above 2 examples annd try to assign these functions to variables.

function doSomethingCool(){
 console.log('I do something cool');
}

var makeSomeNoise = doSomethingCool;


Oh! Scary! Well, if you've ever worked with Java, then it might be. However there are some similarities between the two languages. When you assign the function doSomethingCool to the variable makeSomeNoise, you are simply creating another reference to the function. Now both the objects - makeSomeNoise and doSomethingCool refer to the same function. That is why, if we wished to, we could rewrite the first Method of function declaration using the second syntax! See the code below

var doSomethingCool = function(){
 console.log('I do something cool');
}


This way of declaring the function doSomethingCool is exactly equal to the Method 1, the only difference being the syntax. The point to be noted here is that a function name is actually nothing but a variable declared in the local scope.

Although the 'not so cool way' of defining functions is extremely convenient to use, the above syntax in which you assign a variable to an anonymous function makes it extremely easy to always remember that a method name is nothig but a javascript object, albeit not an ordinary one. I will elaborate more about that in the upcoming articles.





Now that you know that function names are actually objects, you can do some weird stuff with it. Something that you could have never do using Java. For example, take a look at the code below

//Define the function
function doSomethingCool(){
 console.log('I do something cool');
}

//Invoke the function
doSomethigCool();

//Assign the function name to point to a different function
doSomethingCool = function(){
 console.log('I do something hot');
}

//Invoke the function again
//This time the function will print a different message
doSomethingCool();


Check your browser's console to verify the output. (Just in case you dont know, if you are using Google Chrome you can press F12 or Ctrl+Shift+I to open the chrome developer tools and click on the "console" tab. If you are using Firefox, you need to install the Firebug extension and then you can press F12 to get the firebug console and then select the "console" tab to view the console messages)

Another cool thing that you might want to know about functions is the way in which it is invoked. In the above examples, we created a few functions and assigned names to them. After that we were able to invoke them using the ordinary function invocation syntax. But what do we do if we want to invoke an anonymous function? The solution is simple(and interesting!)

(function(){
 console.log('I am anonymous');
}) ();


Notice the braces that enclose the anonymous function definition and the bracecs that follow the function name. Using the above syntax, you can invoke not only an anonymous function, but any function. lets see an example.

var usefulStuff = (function makeUsefulStuff(){
 var bingo={desc:'My name is Bingo'};
 return bingo;
})();


Observe the syntax closely. I have simply created a function and invoked it. Inside the function, I created a local variable in the function called 'bingo' and that's what I returned from the function. The immediate function invocation causes the return statement to execute. So, now, the variable usefulStuff and the variable bingo point to the same object. Note that in this case, just because we invoked the function immediately, usefulStuff does not reference a function, instead it references an ordinary object that was returned by the function. Its is quite possible that when reading someone else's code you might forget to read the braces. After all, they are so tiny and close together. But, just in case you find yourself expecting one object and actually getting another, remember to look for a sneaky pair of braces somwhere after the function defintion and you might just save yourself a buttload of hair.





Coming back to the topic of declaring functions as object properties, the sytnax is pretty simple. Check out the sample code below

//Create an object;
var coolObject ={};

//Declare a function on the object
coolObject.doSomethingCool=function(){
 console.log('Do something cool');
};


Although we say that we are declaring a function on an object, we are actually doing nothing but creating a new property on the object that refers to a function definition. Which means that you can even do the following.

var coolObject ={};

//Declare a function on the object
coolObject.doSomethingCool=function(){
 console.log('Do something cool');
};

coolObject.doSomethingCool();

//What!! You can even make it a string now! No way!
//But apparently you can!
coolObject.doSomethingCool = 'I am a string';

console.log(coolObject.doSomethingCool);


This seems to work because the property 'doSomethingCool' was nothing but a reference to a function. We can reassign it to anything that we wish to at any point of time.





Well, that covers a few nuances of functions. But there is a lot more cool stuff that we will uncover in the upcoming articles! Stay tuned!

Happy Fungramming!
Ryan

No comments: