Material based on the lecture by Carlos Scheidegger

If you’re following the text below, my suggestion is that you either open the Developer Tools’s JavaScript console on a browser window, and type the examples to see what they do, like we go over in class. You should also try variants, and just generally play around with the console, to get a feel for the language.

Before we get started, though, a few words of warning: there is a lot of bad JavaScript advice on the internet. For example, although StackOverflow is typically a high-quality Q&A website, I would stay well away from it when it comes to JavaScript (why that is the case is beyond my understanding). Finally, the introduction below is not meant to give you a comprehensive description of JavaScript, but rather a foothold.

Once you become proficient in the language, then you can start worrying about best practices and special cases, especially as they related to performance and portability across browsers. It’s easier for you simply not to worry about that kind of stuff right now. (This does mean that if you’re a veteran JavaScript programmer, you’ll spot places where what I’m writing is not 100% accurate. If you were to complain, you’d be technically correct (which is the best kind of correct), but what are you doing reading a JavaScript beginner’s guide?

JavaScript Background

Why do we want to use JavaScript? So far we have only written static HTML and SVG code. In your homework, for example, you have to encode a dataset by hand multiple times: for your line-chart, bar chart, scatterplot, etc. If we had a dynamic and general way to load the data, we could use the same variables for all charts and we could also plot the charts with various datasets of different size and with different characteristics. I like to think of pure HTML and SVG as analogous to pen and paper - you can create things that look nice once, but you can’t re-use them efficiently and you can’t interact with them. Computer programming brings interactivity and generalizability (re-use) to the table. We can tell the computer how to do something for certain classes of (legal) input, and the computer will do that for all possible cases of legal input.

JavaScript is the most important programming language of the web, and the only programming language that can be used on most web-browsers without any plugins. Alternatives such as Java Applets or Flash were popular in the past but have lost significant ground to JavaScript. JavaScript is mostly used on the client-side of a client-server application, other languages such as Java and Python are popular on the server, but JavaScript is nowadays also used on the server e.g., using Node.js. We will be focusing on the client-side in this class.

JavaScript can be used with imperative/procedural, object-oriented, and functional programming styles.

It is a dynamically typed language, which can be strange for developers who mainly work with strongly typed languages such as C/C++ and Java.

Also, Javascript uses prototypical inheritance instead of a class-based model for it’s object oriented purposes. That means that there is no “class” that is defined centrally, instead you rely on objects’ prototypes for inheritance that can be extended at runtime. If this doesn’t mean much to you now, don’t worry - we’ll go through it slowly.

JavaScript - The Very Basic

If you know any other mainstream programming language, JavaScript will feel sufficiently familiar.

We can write to the console (helpful for debugging by calling the log method of the console object). Hint: open up your browser’s developer tools to see the output generated by the examples here.

See output in new page.

It has variables which hold values:

See output in new page.

The first thing to notice is that JavaScript’s variables are dynamically typed: you don’t need to declare their types before using them, and they can refer to values of different types at different times in the program execution. (This is convenient but quite error-prone: it’s usually a bad idea to make too much use of this feature.)

You also do not need to declare a variable ahead of time. If you don’t, then JavaScript either assumes you’re referring to an already existing variable, or it creates a new global variable. Again, this is convenient but very error-prone (this is a theme, as you’ll see). One common source of confusion is that typos in variable assignments are not caught: they just become global variables.

To create a local variable, use the keyword var. Local here refers to the current execution context. When used within a function these variables are private to that function, however, when they are declared outside a function, as in the above example, they are still global.

As a general rule: minimize your use of global variables, and never define global variables in a function.

You can execute operations on these variables. Below are a couple of important examples, refer to the MDN documentation for the full list:

See output in new page.

Arrays

Array literals are declared using square brackets and addressed with square brackets and a reference to the index starting with 0. Arrays in JavaScript are more like Lists in other languages, such as Java. They don’t have to be allocated ahead of time and can be easily extended.

See output in new page.

You can do much more with arrays than shown here, again, check out the MDN documentation. Arrays are very important for data visualization, so take the time to go through this!

Objects

Objects are the second type of compound values in JavaScript.

Objects in JavaScript are also dictionaries/hash maps/associative arrays (pick your favorite name).

See output in new page.

Control Structures

JavaScript comes with standard conditional control structures - if and switch.

See output in new page.

Loops

Loops are C-like: for, do-while and while loops are available. To loop over arrays, use either a regular for loop, the forEach function of arrays, or the new for-of statement.

See output in new page.

Functions

Functions are one of the key features in computer science and are common to almost all programming languages. JavaScript uses function both the way we know them from languages such as C or Java, but also allows anonymous functions.

See output in new page.

None of the calls above cause runtime errors. If you call a function with too many parameters, JavaScript will simply ignore the extra ones. If you call a function with too few parameters, JavaScript gives the local parameters the special value undefined.

Local variables in JavaScript use scope as you’d hope they would:

See output in new page.

There is an alternative way of defining functions:

See output in new page.

Pay attention to what’s happening here: this is assigning a value to a variable, in the same way that x = “hi” assigns the string value “hi” to the variable x. But that value is a function! This is important. In JavaScript, functions are values that can be stored in variables. This is your first exposure to the idea that JavaScript is a “functional” language. In the same way that you can store function values in variables, you can pass them around as parameters, store them in arrays, object fields, and even use them as return values of other functions! This is a powerful idea that we will use a lot.

In particular, we will use a lot of anonymous functions, or “lambda abstractions” when working with D3. We’ve already used one example for sorting an array above. Here is another example:

See output in new page.

Object Oriented JavaScript

If we create an object with slots that hold functions, this starts to look like methods from Java and Python. If we create a function that returns these objects, this starts to look like class contructors:

See output in new page.

Inheritance, without Classes

JavaScript does support a notion of inheritance, but it does it without any classes. This means that there’s no subclasses, so how does it work?

Instead of subclasses, JavaScript has the notion of a prototype chain. Every JavaScript object has a special field which points to another object. Then, every time you tell JavaScript to access a field from an object, it tries to find the field. If the field exists, then the lookup is performed. If, however, the field doesn’t exist, then JavaScript checks for the presence of a special prototype field in the object. If that field is not null, then the JavaScript runtime performs a recursive access of the field in the prototype object. This is more obvious with an example. Make sure to run these in your JavaScript console:

See output in new page.

Note that ECMA Script 6 adds syntax for classes, but this is only syntactic sugar, i.e., JavaScript remains a prototypical language.

The special variable this

JavaScript has a special variable that is available at every scope called this. When a function is called with a notation that resembles methods in typical object-oriented languages, say obj.method(), then this is bound to the object holding the method (in this case obj). this allows you to make changes to the local object:

See output in new page.

So far, so good: we’ve used this to change the value bound to the x field in the object. That’s pretty convenient.

However, the convenience comes with a caveat. The way JavaScript decides to associate this with a given object is simple to explain: it assumes the context of the calling object.

Here’s what can go wrong:

See output in new page.

What happened in the example that goes wrong is that when t() is called, this is bound to the calling object, which is the global window object in the latter case.