This Just In: JavaScript is a Real Language

May 11, 2009

Some people think of JavaScript as that crappy language that runs inside of browsers. The truth is that the languages is not that bad, aside from a few warts (void, explicit return, global by default, I'm looking at you), it's pretty nice. I think it's gotten a bad rap for a few reasons.

First of all, the DOM. Before modern JavaScript libraries like jQuery and Prototype came along, developers were constantly pulling their hair out dealing with incompatibilities across different browser implementations of the DOM. Modern libraries have done a lot to normalize behavior across browsers and browser implementations have gotten better, but many developers still have bad memories of dealing with "JavaScript" back in the day. The truth was this wasn't really a problem in JavaScript the language, more so the DOM and browser implementations. If the language that Netscape put into the browser originally was Ruby, we would blame Ruby for all of these problems too.

Next, I think there was a whole class of Java developers upset that OO didn't work in JavaScript the way it did in Java. JavaScript wasn't considered a "real" OO language and was therefore inferior to Java. JavaScript has it's own way of dealing with OO and the sooner you understand how that works, the more comfortable you will be with JavaScript.

In the opposite way that many Java developers despised JavaScript, many Ruby developers, including Java developers converted to Ruby developers, started to appreciate JavaScript. JavaScript has anonymous functions just like Ruby has anonymous functions. Ruby makes ubiquitous use of anonymous functions through blocks. I think for many developers, Ruby was the first language they used that showed how useful anonymous functions can be. I think this is also the reason that you see some many Ruby developers interested other functional languages like Erlang, Haskell and Lisp.

Lastly, I think many developers don't see JavaScript as a general purpose language simply because it's trapped inside the browser. You can't run a JavaScript script from the command line just like you can run a Ruby, Python or Perl script.

Well, it turns out that last one isn't true and I want to show you how to get started writing some JavaScript as a "real" language, and specifically, a functional language.

The first thing you'll need is a JavaScript interpreter. There are many JavaScript interpreters available, such as:

  • SpiderMonkey, the C-based JavaScript interpreter for the Mozilla Gecko rendering engine
  • V8, the C++-based JavaScript interpreter for the Google Chrome browser
  • Rhino, the Java-based JavaScript interpreter.

Let's go with SpiderMonkey.

If you are on a mac and you want to get up and running with SpiderMonkey, the easiest thing to do is sudo port install spidermonkey.

If you want to build it from source, download the tarball and untar it somewhere on your machine. I did that in the src directory in my home directory. Then you go into the js/src directory and run the make command. Here's what that looks like:

cd ~/src
tar xvzf js-1.8.0-rc1.tar.gz
cd js/src
make -f Makefile.ref

Now you should have a directory like Darwin_DBG.OBJ, it will be named differently if you aren't on a Mac. Inside that directory there is a js program you can run. To make life easier, add ~/src/js/src/Darwin_DBG.OBJ to your path, or create a symlink in /usr/bin to ~/src/js/src/Darwin_DBG.OBJ/js.

Now either way, whether you installed spidermonkey via mac ports or from source, you should be able to just type js from the terminal and be at an interactive JavaScript interpreter, with js> as the prompt:

$ js
js> print("Hello, World")
Hello, World

You can also run js my_awesome_script.js to run a script saved in a file. I have created a textmate bundle that has a run command for javascript files. If you install this, then you can press Cmd-R to see the output of the file.

So now let's write a little JavaScript. First things first, open a file called hello.js in Textmate and put this into it:

print("Hello, World!")

If you've created the command properly, you should see Hello, World! printed out. If you aren't using Textmate, then you will have to figure out how to get your editor to run the file. Even if you can't do that, it's as simple as running js hello.js from the command line.

Now we can write some real code. What we want to focus on doing is functional programming. Most of the basic functions for functional programming aren't defined in JavaScript by default, but it's easy enough to write our own that handle the basic things. Note that this kind of functional programming is going to be functional in that we are going to pass functions to and return functions from functions, a.k.a higher-order functions, but we aren't going to focus on other popular aspects of functional programming such as immutable data and pure functions. Baby steps. :)

So the first thing we need is some kind of implementation of an iterator function, because we're not writing for loops. Let's do something like Ruby's each:

function each(f, arr) {
  for(var i=0; i < arr.length; i++) {
    f.apply(null, [arr[i]])

What this does is take a Function and an Array and applies the Function to each element of the Array. To test this out, let's also add this line of code to test it:

each(print, [1,2,3,4,5])

You can see that we can pass the print function to each and have it print the numbers from 1 to 5. Ok, next up is map, which takes a Function and an Array and returns a new Array which contains the result of applying the Function to each element of the Array.

function map(f, arr) {
  var result = []
  each(function(e) {
    result.push(f.apply(null, [e]))
  }, arr)
  return result

We can test that out with:

  return e * e
}, [1,2,3,4,5]))

This time, we are passing an anonymous Function as the first argument to the map Function. This Function takes one value and multiplies it by itself, better know as square. Now for our last trick, we will do the functional programming equivalent of hello world, fibonacci:

function fib(n) {
  if(n <= 1) {
    return n
  } else {
    return fib(n-1) + fib(n-2)

We can test this with:

each(print, map(fib, [1,2,3,4,5,6,7,8,9,10]))

Here's the entire code in one gist.

Now that JavaScript is being viewed as a "real" language, it's even got it's own conference! There's also some IRC channels devoted to JavaScript as well and of course, Stack Overflow. Happy JavaScripting!

Posted in Technology | Tags V8, Javascript, Rhino, SpiderMonkey | 6 Comments