Section 4:   Introduction to JavaScript

JavaScript is a programming language that is used on Web pages. It was first developed by Netscape (the predecessor of Firefox) at about the same time that Java was introduced, and the name JavaScript was chosen to ride the tide of Java's increasing popularity. In spite of the similar names, the two languages are quite different. In fact, there is no standardized language named JavaScript. The standardized language is officially called ECMAScript, but the name is not widely used in practice, and versions of JavaScript in actual web browsers don't necessarily implement the standard exactly.

We will mostly be interested in the parts of JavaScript that relate to graphics, using the HTML <canvas> element. A canvas is a drawing surface that can appear on a web page, in much the same way that a JPanel is a drawing surface that can be used in a Java application. Canvas is a relatively recent addition to the Web, but it is implemented in all modern browsers. Internet Explorer was the last major browser to add canvas support, but it is implemented in Internet Explorer 9 and later. Unfortunately, this means that there are still a lot of people using browsers that don't support canvas. On the other hand, fortunately for us, all the browsers that do support it use a fairly standardized version of JavaScript, and that will allow us to ignore most of the incompatibilities that have plagued web developers.

This will be a very cursory introduction to JavaScript, covering just the parts that we will need. The coverage here is meant for people who already know Java. If you really want to learn JavaScript in detail, you might consider the book JavaScript: The Complete Guide, 6th edition, by David Flanagan.

The Core Language

JavaScript is most closely associated with web pages, but in fact it is a general purpose language that is used in other places too. There is a core language that has nothing to do with web pages in particular, and we begin by looking at that core.

Variables and Types.  Variables in Java are not typed. That is, when you declare a variable, you don't have to declare what type it is, and any variable can refer to data of any type. Variables are declared using the keyword var, and they can optionally be initialized when they are declared:

var x, y;
var name = "David";

A variable that is declared in this way inside a function is local to that function. ("Function" is the term used for subroutines in JavaScript.) You can also use global variables in a function, that is, variables that are declared outside the function. JavaScript, by default, allows you to use variables without declaring them. However, doing so is generally not a good idea. You can prevent the use of undeclared variables, as well as certain other unsafe practices, by including the following statement at the beginning of your program:

"use strict";

Although variables don't have types, values do. A value can be a number, a string, a boolean, an object, or a function. The fact that a function can be used as a data value is probably a surprise to you; more on that later. There are a number of differences from Java. When you compare strings using the == or != operators, the contents of the strings are compared. There is no char type. Strings can be written with either single quotes or double quotes. There is not a strict distinction between integers and real numbers. Division of integers produces a real number, so that 1/2 in JavaScript is 0.5, not 0 as it would be in Java. Although there is a boolean type, you can actually use any type of value in a boolean context. So, you will often see tests in JavaScript such as

if (x) { ... }

The value of x as a boolean is considered to be false if, for example, x is the number zero or is the empty string or is null. Effectively, any type of value can be converted implicitly to boolean. (JavaScript sometimes does other implicit conversions that you might not expect.)

The operator typeof can be used to check the type of a value, as in typeof x. This expression is a string such as "number", "string", "boolean", "function", or "object", so that you can make tests such as

if ( typeof x == "object" ) ...

Note that typeof x is "object" for objects of any type, including arrays.

Like Java, JavaScript uses the special value null to indicate an empty or non-existing value (but remember that any variable can be null). JavaScript also has a special value undefined which is the value of a variable that has not been initialized. (typeof null is "object", and typeof undefined is "undefined".)

JavaScript does not have type-casting as it exists in Java. However, you can use Number, String, and Boolean as conversion functions. For example,

x = Number(y);

will attempt to convert y to a number. You can apply this, for example, when y is a string. If the conversion fails, the value of x will be NaN, a special value indicating "Not a Number," equivalent to Double.NaN in Java. Aside from the exceptions I've mentioned, expressions are mostly the same in JavaScript as in Java, including things defined in the Math class such as Math.random(), Math.sqrt(), and the constant Math.PI.

Control Structures.  JavaScript control structures are pretty much the same as in Java, including if, while, for, do..while, and switch. JavaScript does not have the "foreach" version of for; instead, it has an explicit foreach control structure that I will not cover here. JavaScript has a try..catch that is similar to Java's, but since variables are untyped, there is only one catch block, and it does not declare a type for the exception. (That is, you say, "catch (e)" rather than "catch(Exception e)".) Any type of value can be thrown. You might, for example, throw a string that represents an error message.

Defining and Functions.  Functions in Java are defined using the function keyword. Since variables are untyped, no return type is declared and parameters do not have declared types. Here is a typical function definition:

function square(x) {
    return x * x;
}

A function can return any type of value, or it can return nothing (like a void method in Java). In fact, the same function might sometimes return a value and sometimes not, although that would not be good style. JavaScript does not require the number of parameters in a function call to match the number of parameters in a function definition. If you provide too few parameters in the function call, then the extra parameters in the function definition get the value undefined. You can check for this in the function by using the parameter as a test in an if statement. There can be a good reason for doing this: It makes it possible to have optional parameters. For example, consider

function multiple( str, count ) {
     if ( ! count ) {
         count = 2;
     }
     var i;
     var copies = "";
     for (i = 0; i < count; i++) {
         copies += str;
     }
     return copies;
}

If no value is provided for count, as in multiple("foo"), then count will be set to 2. (Of course, that will also happen if count is 0 or null or false or the empty string. If you want to be sure that count is really undefined, you can test if (typeof count == "undefined").)

You can also provide too many values in a function call. All the values provided are always available in the function in a special variable named arguments, which is essentially an array. For example, this makes it possible to write a sum function that takes any number of input values:

function sum() {
    var i;
    var total = 0;
    for (i = 0; i < arguments.length; i++) {
         total += arguments[i];
    }
    return total;
}

With this definition, you can call sum(2,2), sum(1,2,3,4,5), and even sum(). (The value of the last function call is zero.) Note that calling sum with non-numeric arguments will not produce an error but will not produce a useful result.

Functional Programming.  Functions in JavaScript are "first class objects." This means that functions are treated as regular data values, and you can do the sort of things with them that you do with data: assign them to variables, store them in arrays, pass them as parameters to functions, return them from functions. In fact, it is very common to do all of these things!

When you define a function using a definition like the ones in the examples shown above, it's almost the same as assigning a function to a variable. For example, given the above definition of the function sum, you can assign sum to a variable or pass it as a parameter, and you would be assigning or passing the function. And if the value of a variable is a function, you can use the variable just as you would use the function name, to call the function. That is, if you do

var f = sum;

then you can call f(1,2,3), and it will be the same as calling sum(1,2,3). (One difference between defining a function and assigning a variable is that a function defined by a function definition can be used anywhere in the program, even before the function definition. The computer reads the entire program and defines the functions before it starts executing the program.)

JavaScript even has something like "function literals," that is a way of writing a function data value just at the point where you need it, without giving it a name or defining it with a standard function definition. Such functions are called anonymous functions. The syntax looks like a function definition without a name. Here, for example, an anonymous function is created and passed as the first parameter to a function named setTimeout:

setTimeout( function () {
    alert("Time's Up!");
}, 5000 );

Arrays.  Arrays in JavaScript are more similar to Java ArrayLists than to Java arrays, since a JavaScript array does not have a fixed size, and it comes with a large number of methods for performing useful operations the array. However, the basic syntax is the same as Java arrays: If the value of A is an array, then A.length is the current length of the array, and elements of the array are referred to as A[0], A[1], A[2], ..., A[A.length−1]. An array value can be created as a list of values between [ and ]. For example:

var A = [ 1, 2, 3, 4, 5 ];
var B = [ "foo", "bar" ];
var C = [];

The last line in this example creates an empty array, which initially has length zero. The push method can be used to add a new element to the end of an array, increasing its length: A.push(6). The pop method removes and returns the last item: A.pop().

Objects.  JavaScript has objects, but it doesn't exactly have classes, at least not in the sense that Java does. An object is essentially a collection of key/value pairs, where a key is a name (like an instance variable or method name in Java) that has an associated value. Note that the value can be an ordinary data value or a function (which is just another type of data value in JavaScript). It is possible to make an object value as a list of key/value pairs, enclosed by { and }. For example,

var pt = {  x: 17, y: 42 };

var ajaxData = {
    url: "http://some.place.org/ajax.php",
    data: 42,
    onSuccess: function () { alert("It worked!"); },
    onFailure: function (error) { alert("Sorry, it failed: " + error); }
};

With these definitions, pt is an object. It has instance variables pt.x, with value 17, and pt.y with value 42. ajaxData is another object with instance variables including ajaxData.url and ajaxData.onSuccess. The value of ajaxData.onSuccess is a function, created here as an anonymous function. Objects, by the way, are open in the sense that you can add a new instance variable to an existing object at any time just by assigning a value. For example, given the object pt defined above, you could say

pt.z = 84;

to add z as an instance variable in the object with value 84. By the way, the term "instance variable" is not usually used in JavaScript; the preferred term is property.

Although JavaScript doesn't (quite) have classes, it does have constructors, which can be called with the new operator to create objects. For example,

var now = new Date();

This calls the constructor Date(), which is a standard part of JavaScript. When called with no parameters, new Date() constructs an object that represents the current date and time.

A constructor is written like an ordinary function; by convention, the name of a constructor function begins with an upper case letter. In some sense, a constructor actually defines a class. Date, for example, is often referred to as a class. It is possible to write a function that can be used as a constructor, and doing so defines something that is as close to a class as JavaScript comes. For example, let's see how to define a class to represent points in 2D:

function Point2D(x,y) {
    if (x) {
        this.x = x;
    }
    else {
        this.x = 0;
    }
    if (y) {
        this.y = y;
    }
    else {
        this.y = 0;
    }
    this.move = function(dx,dy) {
        this.x = this.x + dx;
        this.y = this.y + dy;
    }
}

When called with the new operator, this function creates an object that has properties x, y, and move. The fact that the value of move is a function makes it more like an instance method than an instance variable. Consider:

var p1 = new Point2D(17.42);
var p2 = new Point2D();

The values of these variables are objects, and we would say that they are "objects of type Point2D". p1.x is 42 and p1.y is 17. Calling p1.move(1,2) will change the values of the properties to p1.x = 18 and p1.y = 43. (It is also possible to change these variables directly with assignment statements.) Note that p2 is created with the default value of zero for p2.x and p2.y.

The definition of the move method in this example is not done in the best way possible. The problem is that every object of type Point2D gets its own copy of move. That is, the code that defines move is duplicated for each object that is created. The solution is to use something called the prototype of the function Point2D. This takes us farther than I want to go into programming with objects, but here is a more efficient definition:

function Point2D(x,y) {
    if (x) {
        this.x = x;
    }
    else {
        this.x = 0;
    }
    if (y) {
        this.y = y;
    }
    else {
        this.y = 0;
    }
}

Point2D.prototype.move = function(dx,dy) {
    this.x = this.x + dx;
    this.y = this.y + dy;
}

The properties of the prototype are shared by all objects of type Point2D. In this case, there is only one copy of move, which is used by all such objects.

Although writing "classes" in JavaScript is very different from writing them in Java, using classes once you have them is pretty much the same in both languages.

A few more comments: Making things that act like subclasses is tricky, but possible. I won't discuss it here. The special variable this is subtly different in JavaScript from this in Java. One consequence is that when defining methods in JavaScript, instance variables and instance methods can only be referred to using this. If x is an instance variable, for example, it has to be referenced as this.x in the method definition.

JavaScript on Web Pages

There are three ways to include JavaScript code on web pages (that is, in HTML files). First, you can include it inside <script> elements, which have the form

<script type="text/javascript">
    
    // ... JavaScript code goes here ...
    
</script>

Second, you can put JavaScript code in a separate file, usually with a name ending with ".js", and import that file into the web page. A JavaScript file can be imported using a variation of the <script> tag that has the form

<script type="text/javascript" src="filename.js"></script>

where "filename.js" should be replaced by the URL, relative or absolute, of the JavaScript file. The closing tag, </script>, is required here to mark the end of the script, even though it is not permitted to have any code inside the script element. (If you do, it will be ignored.) Importing JavaScript code from a file in this way has the same effect as typing the code from the file directly into the web page.

Script elements of either type are often included in the <head> section of an HTML file, but they can actually occur at any point, and you can use any number of script elements on the same page.

The third way to use JavaScript on a web page is in event handlers that can occur inside HTML elements. For example, consider

<h1 onclick="doClickHeader()">My Web Page</h1>

Here, the onclick handler defines an event handler that will be executed when the user clicks on the text of the <h1> element. The value of an event handler attribute such as onclick can be any JavaScript code. It can include multiple statements, separated by semicolons, and can even extend over several lines. Here, the code is doClickHandler(), so that clicking the <h1> element will cause the JavaScript function doClickHandler() to be called. I should note that this is not the only way to attach a JavaScript function to an event, and it is considered a somewhat old-fashioned way of doing so. However, I will use it occasionally.

It is important to understand that all the JavaScript code in <script> elements, including code in imported files, is read and executed as the page is being loaded. Usually, most of the code in such scripts consists of variable initializations and the definitions of functions that are meant to be called after the page has loaded, in response to events. Furthermore, all the scripts on a page are part of the same program. For example, you can define a variable or function in one script, even in an imported file, and then use it in another script.


JavaScript on web pages includes several standard functions that allow you to interact with the user using dialog boxes. The simplest of these is alert(message), which will display message to the user in a pop-up dialog box, with an "OK" button that the user can click to dismiss the message.

The function prompt(question) will display question in a dialog box, along with an input field where the user can enter a response. The prompt function returns the user's response as its return value. This type of dialog box comes with an "OK" button and with a "Cancel" button. If the user hits "Cancel", the return value from prompt is null. If the user hits "OK", the return value is the content of the input field, which might be the empty string.

The function confirm(question) displays question in a dialog box along with "Yes" and "Cancel" buttons. The return value is true or false, depending on whether the user hits "OK" or "Cancel".

Here, for example, is a simple guessing game that uses these functions for user interaction:

alert("I will pick a number between 1 and 100.\n"
         + "Try to guess it!");
         
do {

    var number = Math.floor( 1 + 100*Math.random() );
    var guesses = 1;
    var guess = Number( prompt("What's your guess?") );
    while (guess != number ) {
        if ( isNaN(guess) || guess < 1 || guess > 100 ) { 
            guess = Number( prompt("Please enter an integer\n"
                              + "in the range 1 to 100") );
        }
        else if (guess < number) {
            guess = Number( prompt("Too low.  Try again!") );
            guesses++;
        }
        else {
            guess = Number( prompt("Too high.  Try again!") );
            guesses++;
        }
    }
    alert("You got it in " + guesses + " guesses.");
    
} while ( confirm("Play again?") );

(This program uses Number() to convert the user's response to a number. If the response is null or empty or cannot be parsed as a number, then the value will be the non-a-number value NaN. The function isNaN(guess) is used to check whether the value of guess is this special non-a-number value. It's not possible to do that by saying "if (guess == NaN)" since the expression NaN == NaN evaluates to false! The same, by the way, is true of the non-a-number value in Java.)


You can try out JavaScript code in JavaScript consoles that are available in many web browsers. In Firefox, for example, you can access a console with the "Tools" / "Web Developer" / "Web Console" command. This will show the web console at the bottom of the Firefox window, with a JavaScript input field at the very bottom. When you type a line of JavaScript and press return, it is executed, and its value is output in the console. The code is evaluated in the context of the current web page, so you can even enter commands that affect that page. The Web console also shows JavaScript errors that occur when code on the current web page is executed, and JavaScript code can write a message to the console by calling console.log(message), so the console is very useful for debugging. (Note: Once your code is running, you should remove the console.log commands, since they can cause errors on some browsers.) The Firefox Web Developer tools include many useful features, and you might want to keep the console available while working on your code. Note that you can detach the developer tools into a separate window, if you want.

The Chrome browser has its own set of developer tools. Its JavaScript console can be accessed under "Tools" / "JavaScript Console". In the Safari browser, use "Show Error Console" in the "Develop" menu (but note that the Develop menu has to be enabled in the Safari Preferences, under the "Advanced" tab). In Internet Explorer (version 8 and higher), access its "Developer Tools" by hitting the F12 key.

Working with the Web Page

JavaScript code on a web page can manipulate the content and the style of that page. It can do this because of the DOM (Document Object Model). When a web page is loaded, everything on the page is encoded into a data structure, defined by the DOM, which can be accessed from JavaScript as a collection of objects. There are several ways to get references to these object, but I will discuss only one: document.getElementById. Any element on a web page can have an id attribute. For example:

<img src="somepicture.jpg" id="pic">

or

<h1 id="mainhead">My Page</h1>

An id should be unique on the page, so that an element is uniquely identified by its id. Any element is represented by a DOM object. If an element has an id, you can obtain a reference to that element by passing the id to the function document.getElementById. For example:

var image = document.getElementById("pic");
var heading = document.getElementById("mainhead");

Once you have a DOM object, you can use it to manipulate the element that it represents. For example, the content of the element is given by the innerHTML property of the object. The value is a string containing text or HTML code. In our example, the value of heading.innerHTML is the string "My Page". Furthermore, you can assign a value to this property, and doing so will change the content of the element. For example:

heading.innerHTML = "New Headline!";

This does not just change the value of the property in the object; it actually changes the text that is displayed on the web page! This will seem odd to a Java programmer: It's an assignment statement that has a side effect. But that's the way the DOM works. A change to the DOM data structure that represents a web page will actually modify the page and change its display in the web browser.

Some attributes of elements become properties of the objects that represent them. This is true for the src attribute of an image element, so that in our example, we could say

image.src = "anotherpicture.jpg";

to change the source of the image element. Again, this is a "live" assignment: When the assignment statement is executed, the image on the web page changes.

The DOM object for an element has a property named style that is itself an object, representing the CSS style of the object. The style object has properties such as color, backgroundColor, and fontSize representing CSS properties. By assigning values to these properties, you can change the appearance of the element on the page. For example,

heading.color = "red";
heading.fontSize = "150%";

will make the text in the <h1> element red and 50% larger than usual. The value of a style property must be a string that would be a legal value for the corresponding CSS style.

Most interesting along these lines, perhaps, are properties of input elements, since they make it possible to program interaction with the user. Suppose that on a web page, we have

<input type="text" id="textin">

<select id="sel">
   <option>Option 1></option>
   <option>Option 2></option>
   <option>Option 3></option>
</select>

<input type="checkbox" id="check">

and in JavaScript

var textin = document.getElementById("textin");
var sel = document.getElmenntById("sel");
var check = document.getElementById("check");

Then the value of the property checkbox.checked is a boolean that can be tested to determine whether the checkbox is checked or not, and its value can be set to check or uncheck the box programmatically. The value of checkbox.disabled is a boolean that tells whether the checkbox is disabled. (The user can't change the value of a disabled checkbox.) Again, you can both test and set this value. The properties sel.disabled and textin.disabled do the same thing for the <select> menu and the text input box. The properties textin.value and sel.value give the current values of those elements. The value of a text input is the text that is currently in the box. The value of a <select> element is the value of the currently selected option. As an example, here is complete source code for a web page that implements a guessing game using a text input box and buttons:

<!DOCTYPE html>
<html>
<head>
<title>Guessing Game</title>
<script type="text/javascript">
    "use strict";
    var number = Math.floor( 1 + 100*Math.random() );
    var guessCount = 0;
    var guessMessage = "Your guesses so far: ";
    function guess() {
        var userNumber = Number( document.getElementById("guess").value );
        document.getElementById("guess").value = "";
        if ( isNaN(userNumber) || userNumber < 1 || userNumber > 100 ) {
            document.getElementById("question").innerHTML =
               "Bad input!<br>Try again with an integer in the range 1 to 100.";
        }
        else if (userNumber == number) {
            guessCount++;
            document.getElementById("question").innerHTML =
                "You got it in " + guessCount + " guesses. " +
                userNumber + " is correct.<br>" + 
                "I have picked another number.  Make a guess!";
            number = Math.floor( 1 + 100*Math.random() );
            guessCount = 0;
            guessMessage = "Your guesses so far: ";
            document.getElementById("message").innerHTML = "";
        }
        else if (userNumber < number) {
            guessCount++;
            document.getElementById("question").innerHTML =
                userNumber + " is too low.<br>Try again.";
            guessMessage += " " + userNumber;
            document.getElementById("message").innerHTML = guessMessage;
        }
        else {
            guessCount++;
            document.getElementById("question").innerHTML =
                userNumber + " is too high.<br>Try again.";
            guessMessage += " " + userNumber;
            document.getElementById("message").innerHTML = guessMessage;
        }
    }
</script>
</head>
<body>
    <p id="question">I will pick a number between 1 and 100<br>
     Try to guess it.  What is your first guess?</p>
    <p><input type="text" id="guess">
       <button onclick="guess()">Make Guess</button></p>
    <p id="message"></p>
</body>
</html>

Here's one problem with some of my discussion. Suppose that a script uses document.getElementById to get the DOM object for some HTML element. If that script is executed before the page has finished loading, the element that it is trying to access might not yet exist. And remember that scripts are executed as the page is loading. Of course, one solution is to call document.getElementById only in functions that are executed after the page is complete; that's what I did in the previous example. But sometimes, you want to assign a DOM object to a global variable. Where should you do that? One possibility is to put the script at the end of the page. That will probably work. Another, more common technique is to put the assignment into a function and arrange for that function to run after the page has finished loading, when it will be safe. To do that, you have to work with events. When the browser has finished loading the page and building its DOM representation, it fires a load event. You can arrange for some JavaScript code to be called to respond to that event. A common way of doing this is to add an onload event-handler to the <body> tag:

<body onload="init()">

This will call a function named init when the page has loaded. You would provide a definition for the function that includes any initialization code that your program needs.

You can define similar event-handlers in other elements. For <input> and <select> elements, you can supply an onchange event-handler that will be executed when the user changes the value associated with the element. For example, this allows you to respond when the user checks or unchecks a checkbox or selects a new option from a select menu. I mentioned the onclick event-handler above, which can be applied to any visible element but is probably most useful for buttons. There are several other events that are generated by the mouse. For example, onmouseover is for the event that occurs when the mouse is moved into an element, and onmouseout is for when the mouse moves out of the element. It might be worth mentioning that in the event-handling code, the special variable this can be used to refer to the element on which the event occurs. For example:

<p onmouseover="this.style.backgroundColor='yellow'"
       onmouseout="this.style.backgroundColor='white'">
    Move your mouse over me!
</p>

Furthermore, a mouse event handler can use a special variable event to refer to an object that contains information about the event. For example, event.clientX and event.clientY give the location of the mouse in the browser window:

<p onclick="alert( 'Clicked at ' + event.clientX + ',' + event.clientY )">
    Click me!
</p>

Of course, it would be more likely to call a function in response to the event, as in onclick="doClick(event)".

As nice as all this is, it's not the preferred way of setting up event handling. For one thing, the mixing of JavaScript code and HTML code is often considered to be bad style. And there is another way to do it that offers more flexibility: Use the addEventListener function, which is defined as a method in DOM objects (at least in modern browsers, including all of those that support the HTML canvas element). If elem is a DOM object representing some element, you can, for example, use the following statement to set up event-handling for mouse-click events on that element:

elem.addEventListener( "click", handler, false );

The first parameter is a string that gives the name of the event. The name is the same as the name of the event attribute in HTML, with "on" stripped off the front: onclick becomes "click". The second parameter is the function that will be called when the event occurs. It can be given as the name of a function or as an anonymous function. The event object will be passed to that function as a parameter. The third parameter is harder to explain and will, for our purposes, always be false.

This technique is more flexible because of the third, boolean parameter (which I'm not about to explain) and because it allows you to set up more than one event handler for the same event.