Wednesday, May 2, 2012

Naked JavaScript - Constructor Functions

In the part 4 of the series - Naked Javascript, we are going to take a deeper look at Functions in Javscript and explore its twisted syntax and various implications. In the previous article, we learnt about the different ways in which you can invoke functions. In this part, we examine the stuff that is responsible for creating functions in JavaScript.

Functions in JavaScript are fantastic. Not only are they used to execute functionality, but they are also used to create other objects and functions(Yes, you read that right). Functions are means by which you implement a very significant feature of the language - inheritance. We will be talking about the details of inheritance later. For now, lets continue exploring functions.

Like all amazing and awesome things in the world, when you talk about functions in Javascript, there is more to it than meets the eye. The real way to figure out what more is out there is by firing up your browser console and dissecting it bit by bit.

Lets first try to answer a very basic quesion. What exactly is a function? Well, a function is nothing but a Javascript object. Yes I know that I have said that numerous times in the previous parts of the series, but believe me when I say that it is impossible to stress this point any less.

However, functions are objects with a few special features that makes them stand out from ordinary objects. In order to understand what functions are you first need to know who creates functions.

In javascript, in order to create objects, all you need to do, is define a constructor. Unlike other programming languages(e.g. Java), you dont need any special wrapper around a function, i.e. your constructor does not have to defined inside of a class. A constructor is just an ordinary function. For example

function Employee(){
 //blah blah
 console.log('Employee function');
};

This is a simple constructor function. There is nothing special about this function. The only thing that is different here is the fact that we followed a different naming convention by capitalizing the first alphabet of the function name. This convention is recommended and important when you are declaring constructor functions because it lets others differentiate between ordinary functions and functions that are designed with the intention of be used as a constructor function.

Now this function does not seem to be doing anything special. But in Javascript, you can do something totally strange. You can create instances of functions. For example, once you have declared a employee constructor function like the one above, you can do somethig like this.

function Employee(){
 console.log('Employee function');
};

var emp1 = new Employee();

The syntax is both befuddling and amusing. Lets try to understand the what exactly is happening under the hood here when we invoke a function along with a new operator.

This syntax of invoking functions that are meant to be constructor functions was designed to appeal to Java programmers. When you invoke a function using the 'new' keyword, the runtime creates an empty object and passes that object to the function. That object then becomes the value of the 'this' keyword inside the function. I will be covering the 'this' keyword in JavaScript in details in a later part of this series. But for now, assume that when invoked using the 'new' keyword, the 'this' inside the function behaves similar to the 'this' keyword used in Java. Once the function finishes its execution, the function automatically returns a reference to the 'this' even though you did you explicitly write a return statement at the end of the function. Note that had you invoked the Employee() function without the 'new' keyword, no new object would have been created, and our Employee function would have returned nothing without an explicit return statement.

After the function execution, the variable emp1 now points to the newly created object. You can think of this object to be an instance of the function. I say so because if you try to execute 'emp1 instanceof Employee', it returns true. The 'instanceof' keyword is an easy way to determine the name of the function responsible for constructing an object.

Not only that, every object has access to a property called 'constructor' that tells you about the constructor of that object. For example, you could do something like this.

function Employee(){
 console.log('Executing Employee function');
};

var emp1 = new Employee();
var dummy = {};

console.log(dummy.constructor);
console.log(emp1.constructor);


When you run it on chrome, you would be able to see the following lines on the console.


Executing Employee function
function Object() { [native code] }
function Employee(){ console.log('Executing Employee function'); }


The first line is the normal console.log that was executed when you created a new function object. Thats not much of a mystery anyways. But then, you see another line that says "function Object() { [native code] }". This comes from the log of dummy.constructor. And then in the next line, you see all the dirty little details of our own 'Employee' function. (This point should give you ideas!).

Ok, now that we understand how to create a custom constructor function and create instances using the constructor function, lets have some more fun with functions.

Remember when I said that, that functions are objects too?. And this directly implies that there has to be some constructor function that constructs functions(Tongue twister alert!). Dare to explore? Yes sir!

function Employee(){
 console.log('Executing Employee function');
};

console.log(Employee.constructor);


Turns out that there is a function called "Function" that does the magic of constructing functions for us(This should be your Eureka moment, ryt!! Or, maybe its just me).

So we have a function that creates other functions and it is aptly a function called - "Function". Also note that the naming convention for a constructor function is being followed here. Hey, guess what? Even anonymous functions have the same constructor. Of course they do, since they are functions too(Love that rhyme, dont you?).

console.log((function noname(){}).constructor);


Well, am gonna let curiosity kill the cat and find out who makes the Function function too, because hey, even thats an object, ryt?

console.log(Function.constructor);



It seems that the Function function creates itself. (Ok, now the cat's dead ). 


Now that you know that a function creates a function, this gives you the ability to formulate a new syntax to create functions. 


var dynamicFunction = new Function();


However, the function that we just created is not of much use in this way, because we don't have a function body. But hey ho!, you can create your function with full fledged parameters and the function body as shown in the example below. 

var nowThisIsWeirdButCool = new Function('p1','p2','console.log("Stripping "+p2+" "+p1)');
nowThisIsWeirdButCool('Naked','Javascript');


As you can see, this is a pretty convoluted way of defining functions, but still, it certainly is one of the ways in which you can choose to create functions in JavaScript. Amazing right? But, note that is a really BAD BAD BAD way to create functions because functions created using this technique make use of the sacred JavaScript function 'eval' in order to evaluate the definition of the function body provided as a string parameter at runtime. The use of the eval() function is considered to be evil. ( Need I say that the two words even rhyme to a certain extent. See my point?). 

To conclude, this post uncovered a few more aspects of functions in JavaScript. As I said before, functions are the building blocks of so many things in JavaScript, that is is quite impossible to talk about anything in JavaScript without talking about functions and their various idiosyncracies. 

However, this is all that I have for this part of the series. There's more coming. Stay tuned for the next! 

Happy Programming :)
Signing Off

Ryan

No comments: