Wednesday

Quit being lazy. lern2javascript noob

[Note: This is a blog post from a year ago, but I'm reviving it because I'm seeing developers and companies lose work because they don't have JavaScript experience. If you work on web applications, you need to learn JavaScript. In addition to this post, which targets Java developers, I've added links to good getting started resources at the end.]

Prologue: Why you need to learn JavaScript

For the foreseeable future (probably the next 5-10 years), the majority of software development will be done on web applications. Many of these will be ports of existing desktop applications or designed to replace such applications. Developing desktop-like applications on the web is going to require that Ajax thing you've been hearing about, something called DHTML, DOM, etc. That means you'll be using JavaScript.

We Java developers have been conditioned to flee at the first mention of JavaScript which has meant that it has long been the job of the 'creatives' to do the JavaScript work. That's not going to cut it anymore. While the work UX experts do is crucial to developing any application, they have different training, priorities and experiences. RIAs need solid technical developers who understand best practices, patterns, unit testing, etc. and can apply them to JavaScript.

One way Java developers try to avoid having to deal with JavaScript is through frameworks like JSF or GWT. There are certainly advantages to using a framework, but they are no substitute for being comfortable with JavaScript. Developing RIAs through a framework without knowing JavaScript is like using Hibernate without a solid understanding of SQL and relational databases. You may get by, but it wont be easy and it wont be pretty.

Hopefully you're now convinced that JavaScript is in your future. I want you to know that you don't have to be dragged into it kicking and screaming. It will be fun. You know those closure things that they're talking about putting in Java 7? JavaScript has always had them. Ever get tired of writing the same Java code over and over? JavaScript code is far shorter and less repetitive.

Differences: The Good, The Bad, and The Ugly

I'm going to focus on the immediately important differences for now. We'll pick up the more subtle ones as we go.

  • JavaScript, like Java, has a C like syntax so you should feel pretty much at home. It has fewer keywords than Java, but adds a few new ones. The most important one is function, which we'll talk about more in the next chapter, but there's also var(declares a variable), with (to generally be avoided), and in (multiple uses).

  • JavaScript is loosely (weak) typed. For a UI, that's a good thing, because most of the data you're working with is string data, so you don't have to declare String everywhere and if you need a string to occasionally be a number, it happens automatically. Every object has a boolean value of true except 0,the empty string and false. An undefined or null variable also evaluates to false, so you can check to see if an object has the method/property that you want like so:
    if(!foo.bar) {
    throw "foo must have bar";
    // you can throw anything to raise an error
    }
    Of course, you can do whatever you like if the object you were passed doesn't have a particular method.

  • There are only Numbers in JavaScript. There is no distinction between int,float, double and long. Math.round, Math.floor and Math.ceil are there if you need them. The maximum value is 1.7976931348623157e+308 so don't worry too much about overflowing. You shouldn't be doing any heavy computation on the client anyways. If you try to do arithmetic with something that isn't a number, the result will be NaN (not a number). NaN and anything is NaN. That includes undefined variables:
    var foo = 1;
    foo + bar; // == NaN, since bar is undefined
  • There is no char type. You can use either single or double quotes to delimit a string. 'f' is always the string "f". charCodeAt(index) on strings will give you the character code as a number.

  • In addition to functions, objects and arrays are first class citizens (technically functions and arrays are also objects). You can define array literals using the [] syntax: var myArray = [1,2,3];. For objects you use {} and provide a list of name:value pairs: var myObj = { foo: "bar", baz: [1,2,3] }. Both array and object literals can span multiple lines. It's generally good form to break lines after a comma (if you must break lines):
    var foo = {
    bar: "baz", qux: 123,
    quxx: { a: 1, b: 2, c: 3}
    };
  • Perhaps the most important JavaScript data type is the function. We wont get into it now, but you need to know that you can treat functions like any other variable. e.g.,
    var foo = function(a,b) {
    return a + b;
    };

    foo(1,2); // == 3
  • When a function is called as a property of an object, it gets access to this. e.g.,
    var foo = new Object();
    foo.bar = function(a) {
    return a + this.b;
    };
    foo.b = 2;
    foo.bar(1); // == 3
    foo.bar(2); // == 4

  • Note that while you can get put a reference to foo's bar function in a variable, it will no longer have access to foo via this.
    var bar = foo.bar;
    bar(2); // == NaN (not a number)
    Since this.b is undefined, 2 + undefined is NaN. You might be wondering why this.bar doesn't result in an error. Well, it's because this is always defined. Since JavaScript executes in the context of the browser window, the default this is the window. This is where all global variables live. Incidentally, you can reference the window explicitly with the window object.

  • There is a difference in scoping in JavaScript as well. You're used to having block local variables. Well, in JavaScript variables are either global or function local. Blocks share their enclosing scope, so
    var foo;
    if(true) {
    foo = 1;
    }
    is the same as
    if(true) {
    var foo = 1;
    }
    foo will still be visible after the else block. If you fail to define a var inside a function, a global variable is created (or if it exists it is overwritten). e.g.,

    function() {
    foo = 1; // sets window.foo = 1
    }
    So, think carefully about scope when you declare and use variables.

  • JavaScript is interpreted, which means that you don't even know 100% if a line of your script is valid until it actually runs. That makes unit testing crucial. Fortunately tools like JUnit, Javadoc, etc. all have JavaScript equivalents that will seem very familiar. There are also a host of development tools including Eclipse plugins, Aptana, IntelliJ support, etc. to help you along.

  • Lastly, you should know that JavaScript inheritance is prototypal. It is fully possible to achieve class based inheritance, which we will do with the help of a library called Prototype, but the prototypal nature of JavaScript gives us some interesting options which we will explore later.

Your Environment

We're Java developers, so we know the power of a good IDE. Eclipse, NetBeans and IntelliJ all have decent JavaScript support. There are a variety of plug-ins for Eclipse (I use JSEclipse), but I'm going to tell you right now that none of them will give you the code completion that you're used to. It's simply not possible with a dynamic, weakly typed language. You'll have to learn APIs the old fashioned way, by reading the docs and using them.

Fortunately, JavaScript gives you an amazing debugging and exploratory tool that you have never had and likely will never have with Java. Its name is Firebug. Go ahead and install it. Done? You need to restart Firefox. OK. Good. Now see in the bottom right corner? Click it. This is Firebug. It does a lot of things, but for now we're just going to mess around with the 'command line'. Do the following:
  1. Click the in the bottom right corner of Firebug.
  2. Paste this into the command line and press Ctrl+Enter or click 'Run':
    $('demoSteps').childElements().each(function(item,i) {
    item.insert("("+i+")");
    });
OK, it's not the most impressive example, but you did just execute code without having to reload the page or anything. Here we're making use of a library called Prototype. Bookmark the API immediately. What the above code does is call a function named '$' (yes, that's a valid variable name in JavaScript) with the argument 'demoSteps'. When $ is given a string, it looks for the element in the HTML with id="demoSteps". We get the child elements and iterate over them, calling the anonymous function we defined there on each element, along with it's index. We then append the index in parentheses to the body of each element.

The equivalent JavaScript without Prototype is a lot longer. You could start learning JavaScript without any libraries, but then you'd quickly get caught up in fixing bugs and writing the same code over an over. Fixing bugs doesn't give you a good appreciation for a language, nor does clunky repetitive code. In any serious web project you will use Prototype or a similar library, so it doesn't hurt to know it. After you're comfortable, we will delve deeper into the JavaScript language and you'll learn what Prototype hides from you.

Before we go, drag this onto your bookmarks toolbar: Insert Prototype. Now you can go to any web page, click that bookmarklet, pop open the console and start using Prototype to play. For homework, explore the Prototype API, especially the utility functions and the Enumerable methods. Try to write as many snippets using the API as you can.

Resources

No comments: