Java development 2.0: JavaScript for Java developers

A Java developer's primer on JavaScript variables, types, functions, and more

Java™ developers have historically perceived JavaScript as a toy language, both too lightweight for real programming and too clunky to be of use as a scripting alternative. And yet JavaScript is still around, and it's the basis of exciting web technologies like GWT and Node.js. In this installment of Java development 2.0, Andrew Glover explains why JavaScript is an important tool for the modern Java developer. He then gets you started with the syntax you need to build first-class applications for today's web, including JavaScript variables, types, functions, and classes.

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew Glover is a developer, author, speaker, and entrepreneur with a passion for behavior-driven development, Continuous Integration, and Agile software development. He is the founder of the easyb Behavior-Driven Development (BDD) framework and is the co-author of three books: Continuous Integration, Groovy in Action, and Java Testing Patterns. You can keep up with him at his blog and by following him on Twitter.



26 April 2011

Also available in Chinese Russian Japanese Vietnamese Portuguese

Back in the early days of the Java platform, it wasn't unusual for journalists, and even occasionally newbie programmers, to confuse JavaScript and the Java language. Both languages were popularized due to their applicability to web programming, after all, and for a few years they ran neck-and-neck in the popular imagination. Most people today differentiate the two languages, but it's still common for Java developers to deride JavaScript as a toy language, not even fit for scripting. The thing is, JavaScript (much like the Java language) has lived on, and even evolved. It's the basis of client-side programming techniques like Ajax and server-side efforts like Node.js, and its importance for mobile application development is beginning to emerge. It's also the language that Java code compiles to in the very popular Google Web Toolkit, or GWT.

In this installment of Java development 2.0, I explain why JavaScript matters to Java developers today and walk through some of the most useful JavaScript syntax, explaining how it differs from the Java language and also contrasting it to more modern dynamic languages like Groovy and Ruby.

About this series

The Java development landscape has changed radically since Java technology first emerged. Thanks to mature open source frameworks and reliable for-rent deployment infrastructures, it's now possible to assemble, test, run, and maintain Java applications quickly and inexpensively. In this series, Andrew Glover explores the spectrum of technologies and tools that make this new Java development paradigm possible.

Then and now: Why JavaScript matters

JavaScript was introduced by Netscape in 1995, and it quickly rose in popularity. The reason had much to do with the emergence of the web as a commercial media platform: With JavaScript you could, and still can, programmatically affect web page behavior within the browser. That was cool stuff then! HTML form validation and limited image trickery were the name of the game.

JavaScript has seen a few incarnations since then. Netscape at one point had a product, Netscape Application Server, that relied on server-side JavaScript for building web applications. Some years later, renewed interest in JavaScript was sparked by the introduction of Ajax and widget libraries like Prototype, JQuery, and Extjs. More recently, server-side JavaScript has come full circle with Node.js, an event-based I/O framework for building server-side web applications using Google's V8 JavaScript engine.

Netscape did something rather forward-thinking for its time by submitting JavaScript to Ecma International for standardization. That's why some people call JavaScript ECMAScript. More importantly, it's why most web browsers support ECMAScript. As a result, Web applications are hard-pressed not to leverage JavaScript somewhere, and that doesn't seem likely to change. There's currently no other browser-compatible scripting language on the horizon.

Node.js

Node.js (see Resources) is a server-side, highly concurrent, event-based framework. Node.js programs scale much more efficiently than programs with threads, while working around a lot of the issues associated with concurrent programming. While Node.js is relatively new, the innovation around it is quite exciting. Knowing JavaScript is key to accessing the growing family of tools associated with Node.js.

Today, even despite its lingering bad reputation, JavaScript is arguably one of the most used (and useful) languages on the planet. If you are a Java programmer (or a Ruby, Python, or PHP programmer), chances are that you've either used JavaScript in the past or you will in the near future. Understanding some of JavaScript's features could help you build the next uber-popular web application. Furthermore, it will enable you to leverage Node.js, and even improve your understanding of what's going on under the hood in GWT.

In the next sections, I'll focus on the main elements of JavaScript syntax, highlighting the little trips and turns that could particularly surprise or delight Java developers. First, however, I want to dispel one of the pervasive myths of JavaScript: that you need a web page to interact with it.


Using JavaScript in Chrome

Historically, JavaScript required a browser, and indirectly a web page, in order to be executed. For some developers that presented an annoyance, and even a hurdle. Fortunately browsers have evolved; today both Firefox and Chrome offer IDEs for executing JavaScript.

I like Chrome's nifty JavaScript console for fooling around with the language. Like Ruby's IRB or Python's shell, Chrome provides an interactive environment for exploring JavaScript without a web page.

CoffeeScript

If you like what JavaScript can do but don't like its syntax, you should take a look at CoffeeScript. CoffeeScript is "little language that compiles into JavaScript" — that is, CoffeeScript makes JavaScript programming easier by relaxing some of its syntax. In many ways, CoffeeScript feels a lot more like Ruby or Python but provides a one-to-one equivalency to JavaScript. See Resources to learn more about CoffeeScript.

To get started with Chrome's JavaScript console, you'll need to download Chrome for your OS. Next, open up a new blank tab (that is, don't point to a web page) and select View > Developer > JavaScript Console. At the bottom of your Chrome window, you'll see the JavaScript developer console pop up. You can make this a standalone dialog by selecting the Undock icon in the bottom left corner of the console. You can then select the Console icon in the dialog's upper-right corner to get to a simple blank window for interacting with JavaScript, as shown in Figure 1:

Figure 1. Interacting with JavaScript in Google Chrome
A screenshot showing Google Chrome's JavaScript console

Now let's look at some syntax.


JavaScript variables

JavaScript is a fairly easygoing language, in that it allows you to make quite a few programming mistakes and still come out with web pages that load. JavaScript elements often fail silently, which is mostly good news. The early web would have been a rough place if sloppy JavaScript programming prohibited pages from loading. That said, as we rely on JavaScript to do fancier things (like asynchronously updating page state), careless JavaScripting does take a toll. It's for this reason that Java developers should take the time to really understand certain aspects of JavaScript syntax.

JavaScript's handling of variables is particularly important to understand. You can define a variable named foo, for instance, either directly or via the var declaration, as shown in Listing 1:

Listing 1. Variable foo
foo = 'foo'
var bar = 'bar'

The foo in Listing 1 is a valid variable in JavaScript. But because it lacks a var declaration, it's a global variable. Variables defined with var are consequently scoped (for example, within the function in which they are defined).

In general, global variables are bad. More often than not they give off code smell, meaning that because they can be accessed and altered anywhere within a JavaScript application, their use can lead to insidious bugs. Thus, when you program in JavaScript, don't forget the var with your variables.


Primitives and objects

While JavaScript is anything but unsophisticated, it is quite simple when it comes to types. In fact, JavaScript really only has four basic types, three of them primitives. JavaScript's primitive types are Number, String, and Boolean. You can see these types in action via JavaScript's handy typeof operator.

Let's try this out together. In Chrome's JavaScript console, type what you see in Listing 2:

Listing 2. Activating types
var string = "test"
typeof string

You should see the console print out the value "string." You'll also note that semi-colons are optional in JavaScript. Like in most popular languages, a string is delineated by quotations; accordingly, numbers are delineated by, well, numbers. Booleans are delineated by the values true or false, without quotations.

Listing 3. JavaScript truth and numbers
var aNumber = 10
var anotherNumber = 0.99
var aBool = true
var notABoolean = "false"

You'll note that JavaScript doesn't differentiate between numeric types; numbers are just numbers, with different formats.

JavaScript also supports generic objects, which in and of themselves have instance types, such as Array, shown in Listing 4:

Listing 4. An instance of Array
> var myArray = ["Hello", 1, true]
> typeof myArray
"object"
> myArray instanceof Array
true

Arrays in JavaScript are much like lists in other languages: they can be created without a size limit and can hold anything you want to throw into them. Like in Ruby or Groovy, JavaScript Arrays can be created with a literal syntax: []. What's more, JavaScript Arrays support methods (shown in Listing 5) you've come to expect in other languages that support lists:

Listing 5. Array's methods
> var myArray = ["Hello", 1, true]
> myArray[0]
"Hello"
> myArray.length
3
> myArray.pop()
true
> myArray
["Hello", 1]
> myArray.pop()
1
> myArray
["Hello"]
> myArray.push("pushed")
2
> myArray
["Hello", "pushed"]

You can obtain an Array's value via its position, which is zero-based. Arrays respond to push and pop, where push adds an item (at its last spot) and pop removes one (like a stack, from the last position).

Arrays also support iteration, shown in Listing 6:

Listing 6. Iterating through an Array
> var myArray = [1,2]
> for(var i = 0; i < myArray.length; i++) { console.log(myArray[i]) }
1
2

Type coercion

JavaScript isn't just a weakly typed language — it's even weaker than Ruby or Groovy! JavaScript goes out of its way to coerce objects into whatever type makes sense at a given point in the code. That makes sense in the context for which JavaScript was originally conceived: web page interaction. Sloppy JavaScript should not prohibit someone from reading an online article!

Type coercion isn't unique to JavaScript, but JavaScript's particular brand is quite flexible. This can be a good thing or a bad thing depending on your point of view. JavaScript's looseness can hide defects, much like global variables do.

For example, I could define an Array and then inadvertently attempt to do something numeric with it, or even some String concatenation, shown in Listing 7:

Listing 7. JavaScript's type flexibility
> var myArray = [1,2]
> console.log(2 * myArray)
> console.log("A" + myArray)

In this case, the first log message would print NaN, while the second would print A1,2. In both cases, the code "worked" in that nothing blew up — JavaScript just kept on trucking. This is weak typing at its extreme. The same code in Ruby wouldn't work like that, as in Listing 8:

Listing 8. Ruby doesn't play that way
> array = ["A", "B"]
> ans = 2 * array

The Ruby code in Listing 8 would error out with:

TypeError: Array
can't be coerced into Fixnum

And if I tried to add "A" to array, it would yield:

TypeError: can't convert
Array into String

If I tried the same trick in Groovy, I would get something like this:

groovy.lang.MissingMethodException: No signature of method: 
java.lang.Integer.plus() is applicable for argument types: (java.util.ArrayList) values:
[[A, B]]

Thus, you can see the various levels of weak typing in action. Clearly, if there was a scale for type weakness, JavaScript would be the wimpiest of them all!


JavaScript functions

A JavaScript function, like a Java method, is a construct for defining and encapsulating reusable behavior. Functions in JavaScript look and feel at first glance a lot like Groovy's closures. Functions in JavaScript are objects. In fact, they are first-class objects, very much unlike methods in Java code. Because JavaScript functions are objects, they can be passed around to other functions and can be invoked at will.

Functions are defined with the function keyword. You can specify arguments like you would in a method declaration in the Java language, plus you can return something from a JavaScript function. Unlike dynamic languages, like Groovy or Ruby, where a return call is optional (and thus the last line of any method is returned), functions in JavaScript must use a return statement if they want to return something; otherwise, they return nothing.

You call functions in JavaScript like you would call closures in Groovy. In Listing 9, I define a simple function that takes no parameters. Its purpose is to print "blah" to the JavaScript console in Chrome.

Listing 9. Defining and calling a function in JavaScript
> function blah() { console.log("blah"); }
> blah() //prints blah
> blah.call() //prints blah
> blah.apply() //prints blah

You can invoke a function directly with parentheses (that is, ()), via the call method, or via the apply method. The first class-ness of function objects is clearly demonstrated here. Listing 10 shows what happens when I try calling a garbage method on function blah:

Listing 10. Functions as objects in JavaScript
> blah.foo()

In this case, you should see an error message complaining that foo isn't a method defined, like so:

TypeError: Object function blah() { console.log("blah"); } has no method 'foo'

Now read that error message again. It's complaining that foo isn't defined, which implies that if it was defined, things should have worked.


Classes in JavaScript

JavaScript supports primitives, which I've discussed. It also supports objects, like Array. JavaScript doesn't support classes — at least not in the classical Java language sense. Because JavaScript is a prototype-based language, you don't define classes: instead, behavior is reused via cloning existing objects. Thus, in JavaScript, you don't define class objects, you define them in functions, then use nested functions to define behavior — something you've already seen in action.

To emulate a class, you define a function. You can give it a name (that is, a class name), specify parameters (as in a constructor), and even use the .this keyword, which basically means referencing a variable within the scope of the function. What's more, inner functions can be aliased to look like method calls.

To demonstrate, in Listing 11 I'll create a Message prototype (also known as a class) that is super simple. I'll provide a few parameters (who the message is from, who it is to, and the actual message) and the class will represent my message as JSON.

Listing 11. Functions as classes in JavaScript
function Message(to, from, msg){
 this.to = to;
 this.from = from;
 this.msg = msg;

 this.asJSON = function(){
  return "{'to':'" + this.to + "', 'from':'" + this.from + "', 'message':'" +
    this.msg + "'}";
 }
}

In Listing 11, I defined a Message function — an object with a name and a few properties; namely, to, from, and msg. I then defined a property (asJSON) pointing to an inner function whose job it is to hand-jam a string representation of my JSON message.

Note that I can also define this "class" in a web page, load it with Chrome, open up the JavaScript console, and use it interactively. That's what's happening in Listing 12:

Listing 12. Using classes in JavaScript
> var message = new Message('Andy', 'Joe', 'Party tonight!');
> message.asJSON();
"{'to':'Andy', 'from':'Joe', 'message':'Party tonight!'}"

This code looks almost like Groovy or even Java code (if not for the var), doesn't it? The fact is, it's totally possible to use OOP techniques for building JavaScript applications (that is, programs containing objects with data and methods interacting with each other).


In conclusion

I hope this article has discredited the notion, now long outdated, of JavaScript as a toy language. In fact it's quite powerful and has a lot of the syntactic sugar and ease of newer languages like Groovy and Ruby. Some of the very qualities that made JavaScript suspect in the '90s are considered desirable today.

Given the importance of the web to much Java application development and the unique place JavaScript holds as a browser-compatible language, every Java programmer should be conversant in JavaScript — period. The browser (whether it be on a computer or mobile device, phone, or tablet) is the means by which more and more people interact with applications. JavaScript is also the common medium between all server-side languages. Besides, understanding some of JavaScript's features will help make you a better programmer in any language, including the one you call home.

Resources

Learn

  • Java development 2.0: This series explores technologies that are redefining the Java development landscape. Topics have included Google App Engine (August 2009), NoSQL (May 2010), and Amazon Elastic Beanstalk (February 2011).
  • "Why you need to learn JavaScript" (Michael Woloszynowicz, Web Development 2.0 and Business Lessons, January 2011): Developers versed in Java programming bring important skills to JavaScript, and JavaScript brings essential tools to web and mobile application development.
  • "JavaScript as a compiler target: Clamato, GWT Smalltalk, Python, Scheme" (Werner Schuster, InfoQ, September 2009): A survey of more recent tools that have modernized the usage of JavaScript, leveraging it for mobile and web application development.
  • "Ryan McGeary on CoffeeScript" (developerWorks, February 2011): McGeary explains how CoffeeScript, which is built on top of Node.js and compiles to JavaScript, makes functional programming cleaner and produces more readable JavaScript.
  • "Why you should pay attention to Node.js" (Stephen O'Grady, RedMonk Tecosystems, May 2010): Discusses Node.js as a disruptive technology for concurrent programming.
  • "Compare JavaScript frameworks" (Joe Lennon, developerWorks, February 2010): More important than the comparison in this article is the in-depth discussion of features that maximize JavaScript development, including selectors, DOM traversal, and event handling.
  • "GWT fu, Part 1" (David Geary, developerWorks, September 2009): Learn how GWT compiles Java code to JavaScript, resulting in rich user interfaces that run in a browser.
  • "Just what is Node.js?" (Michael Abernethy, developerWorks, April 2011): Michael Abernethy gives a good overview of what Node does as well as its current limitations.
  • "Use Node.js as a full cloud environment development stack" (Noah Gift and Jeremy Jones, developerWorks, April 2011): Embrace the concurrency model using asynchronous I/O via callbacks and build a chat server.
  • Browse the Java technology bookstore for books on these and other technical topics.
  • developerWorks Java technology zone: Find hundreds of articles about every aspect of Java programming.

Get products and technologies

Discuss

  • Get involved in the developerWorks community. Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, Open source
ArticleID=650725
ArticleTitle=Java development 2.0: JavaScript for Java developers
publish-date=04262011