Thursday, 15 May 2008

Debugging in IE

When I first started using JavaScript, I used to code and debug using Firebug and then test the same on IE. Obviously sometimes this used to fail due to some porting issues and I would be left with no means to know where and why the code is failing. I am writing this article to share something which will make life easier with debugging on IE for someone who is struggling like me.

I found a world-class free debugger for IE. Visual studio is known for the best debugger out there which can directly attach to any process running on windows, but that doesn't come for free. Microsoft started giving out express editions for free, which has a debugger but that cannot attach to already running processes. Follow the steps below to make express editions help debugging our web-pages on IE.

  • Install Visual Web Developer Express which is free and can be downloaded from
    http://msdn.microsoft.com/en-us/express/aa975050.aspx

  • Enable script debug on IE - go to Tools > Internet Options > Advanced, and make sure "Disable Script Debugging (Internet Explorer)" is unchecked and "Display a notification about every script error" is checked.

  • Start a dummy project with some name.

  • Start IE in debug mode with the created dummy project - Debug->start debugging.

  • The above will start IE with debug enabled and you can open your web-page and enjoy free ultimate debugger.


 

Tuesday, 13 May 2008

"Deep Copy" in JavaScript

Some of you might have come across this issue. When you make a copy of an object and try to change the values of the new instance, it reflects in the original one too. Well I heard this not only applies to JavaScript, but also to most other object oriented languages; not sure though.

Here is a case:



Problem


//original object definition
var oOriginal = {
memNum: 1, // number
memStr: "I am a string", // string
memObj: {
test1: "Old value" // we'll test
},
memArr: [ // array with object members
"a string", // simple string element
{ // an object
test2: "Try changing me" // we'll test
}
]
};

//test 1
var oCopy = oOriginal; // normal copy

oCopy.memObj.test1 = "New value"; // Problem
// - will reflect in oOriginal


alert(oOriginal.memObj.test1); // will show "New value"

//test 2
oCopy.memArr[1].test2 = "I am changed"; // Problem
// - will reflect in oOriginal


alert(oOriginal.memArr[1].test2); // will show "I am changed"


Here the problem is, the objects are never copied, only their references are. So what's the solution? Iterate through all members of the original object, create the same members for target object and then assign corresponding values. And while doing so, we can't forget array of objects.

(Referring to Sunil's comment to this post, we'll add this simple line at the very top to help us detect Array objects. It basically adds our own custom extension to the Array class.)



To recognize Array type objects


<html>
<head>
<title>Deep Copy in JavaScript</title>
<script language="javascript" type="text/javascript">
Array.prototype.__isArray = true;
</script>
.
.


Now, here is the generic method that will help in iterating through all (type of) members of our original object and copy them one-by-one regardless of the depth of the object structure:



Solution


var ObjectHandler = {
//public method
getCloneOfObject: function(oldObject) {
var tempClone = {};

if (typeof(oldObject) == "object")
for (prop in oldObject)
// for array use private method getCloneOfArray
if ((typeof(oldObject[prop]) == "object") && (oldObject[prop]).__isArray)
tempClone[prop] = this.getCloneOfArray(oldObject[prop]);
// for object make recursive call to getCloneOfObject
else if (typeof(oldObject[prop]) == "object")
tempClone[prop] = this.getCloneOfObject(oldObject[prop]);
// normal (non-object type) members
else
tempClone[prop] = oldObject[prop];

return tempClone;
},

//private method (to copy array of objects) - getCloneOfObject will use this internally
getCloneOfArray: function(oldArray) {
var tempClone = [];

for (var arrIndex = 0; arrIndex <= oldArray.length; arrIndex++)
if (typeof(oldArray[arrIndex]) == "object")
tempClone.push(this.getCloneOfObject(oldArray[arrIndex]));
else
tempClone.push(oldArray[arrIndex]);

return tempClone;
}
};


Now we'll perform the same two tests mentioned in the 'Problem' block using this new helper - ObjectHandler



Test


//test 1
var oCopy = ObjectHandler.getCloneOfObject(oOriginal);

oCopy.memObj.test1 = "New value";

alert(oOriginal.memObj.test1); // will show "Old value"

//test 2
oCopy.memArr[1].test2 = "I am changed";

alert(oOriginal.memArr[1].test2); // will show "Try changing me"


In general, this solution is often referred to as "Deep Copy".

Cheers!

Kumar
UI Architect


 

Javascript - Did you get a taste of it yet!?

Javascript is the most under rated language the world has ever seen. Yeah, there might be many more, but the way Javascript had been labeled as an entry level programmer's language for over a decade, nothing can get worse!

Thanks to Google, people suddenly woke up to realize the true potential of Javascript. Before that a million others tried to convince the world that this language has got more than they can imagine, but that hardly helped! I remember this one instance when GMail was launched, and a popular web browser had to come out out with a quick patch in order to make it GMail compatible. Now, if you and I had a similar issue and approached the same people we would be given a hand book on browser standards and compatibilities and asked to learn to live in the 'real world'. Well, this world works on 'brand' capitalization - nothing can replace the power of a brand (except money of course)!

I have always enjoyed coding in Javascript for the last ten odd years. Of course, it took me a long time to realize the true potential of object oriented javascript! My professional work was more in the Java world for a long time. After doing a bit of freelancing using MS Visual Studio, Perl and a few other technologies, I started my regular career on a Java based proprietary framework called WebObjects (this, for those of you who don't know, was at least 5 years ahead of it's time - was more like a combination of Tapestry and Hibernate). After that I went on to work on developing a C library, and later on worked on Tapestry, Hibernate and Spring too. I really enjoy working on a wide variety of technologies, and always prefer to be a jack of all, rather than an expert in something. I believe that being involved in diverse technologies makes you a lot more creative while dealing with tricky situations.

Hmm, now this post is supposed to deal with Javascript, so why am I talking about what I did! Well, now, didn't I mention branding :p! Well, I just want to set the context right guys - I have been there, seen that, and I really know where Javascript stands in terms of churning out amazing code that brings out amazing results. So, if you are a programmer, and if you ever get a chance to deal with raw Javascript, don't think twice - accept it straight away! By the way I didn't use the word 'raw' just like that. Sometime soon I will elaborate on this.

Javascript is basically a 'prototype' based object oriented language. What this means is that you don't describe an object (as in, you don't write a class), but rather use a sample object to define a type. It's a loosely typed language and does not need you to declare types for variables. It can also implicitly convert types as needed. As in Java, Javascript has primitive types and objects. String, number and boolean constitute the primitive types.

Every object in Javascript behaves like a hashmap, and you can determine which property of an object needs to be accessed at runtime. This is a very cool feature, and the last I had dealt with something close to that in Java was while programming using one of the WebObjects frameworks called Enterprise Objects Framework (EOF, please sit up and take note, is like a great ancestor of Hibernate and many other contemporary ORM frameworks). EOF had this base class that enabled a similar functionality using Java's reflection API, and programmers in general wouldn't have to deal with all the complexity of reflection. It definitely helped in trimming down the number of lines while implementing complex business functionality.

Now lets discuss a bit about functions in Javascript. One amazing thing is that every function declared in Javascript is treated like any other object. This means you can actually throw your functions around your code, pass them to other functions, and hold references to them using variables! Hmm, if you ever worked on C, you should be drooling by now - yep, function pointers on steroids, that's what this is!! All those guys from the Java World - sorry guys we have nothing like that in Java (you can try it with reflection, but not really, not enough) - so just make sure you have enough strength to imagine beyond the ordinary to understand the power of function pointers.

Any function in Javascript can be used as a constructor. Now this might confuse beginners, but it's a very simple concept - whenever you call a function preceded by the new keyword, a new object is created and that function is executed in the new object's context (on the lines of a constructor).

Well, now for some not so great news. Javascript does not support function overloading. But I guess there's a valid reason. Javascript allows variable number of arguments to be passed to a function, which means you can pass more arguments than what's been declared for the function! So, then how can those other arguments be accessed? Well, simple, every function has an internal variable called 'arguments' which is like an array of arguments, and all arguments passed to a function can be accessed using 'arguments'.

Well, that kind of wraps up some key features. I will get back with more on Javascript pretty soon!

Kartik Reddy Thum
Senior Dev Engineer