Hello JavaScript, you Handsome Little Thing

JavaScript is a language with history and philosophy. Built in just two weeks, it has a beautiful heart. Unfortunately, 20 years of history has piled up on top of it, obscuring the beauty beneath layers of inconsistent APIs and anti-patterns. Clean away the loose earth and rubble though, and you can see the ancient wonder that lies beneath.

JavaScript inherits from LISP via Scheme. It's a functional language, and not really related to Java at all. The name JavaScript is purely a marketing exercise. Java was the cool thing at the time. The Java like syntax is there to make JavaScript feel more accessible. Underneath however beats a heart of purest Scheme.

Fully Object Oriented

It's object oriented, but on it's own terms. It has no classes, instead, all objects are associative arrays and inheritance is directly from object to object.

Functional

It's also functional. Functions are first class objects and can be passed around. Local variables are attributes of hidden scope objects, and persist as long as they are needed.

Executing JavaScript

We execute JavaScript in a browser by linking to it. with a script tag, like so:

<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script>
</head>
<body>
</body>
</html>

Typically we link to an external file, though we can include JavaScript directly between the tags.

We might make a script.js file and pop a hello world in it:

alert("Hello JavaScript");

Exercise - Hello World

The goal of this exercise is to get an environment set up and working.

  1. Create a folder in which to work.
  2. Create a new HTML file in a text editor. Call it index.html.
  3. Create a JavaScript file in a text editor. Call it script.js.
  4. Put an alert in the script file, like this: alert('Hello world');
  5. Use a script tag to link the JavaScript file into the HTML file
  6. Open the HTML file in a browser. See the alert?
  7. Extend the code so it pops up two alerts.

Variables

Variables in JavaScript are global by default. This is because JavaScript is designed to be easy for non-programmers to use, and non-programmers might not understand about variable scope.

As a real programmer though you should always initialize your variables correctly using the var keyword:

var a; // creates the variable in the current scope
a = 12; // stores a value in the variable

You can create and assign a variable in the same line:

var a = 12;

Single Global Scope

JavaScript has a single global scope which any script can write to. You should avoid creating global variables wherever possible, or sooner or later you will get a conflict.

You may have multiple scripts on the page. Some of these might be advertiser scripts which you don't control. Avoid putting variables in this messy space wherever possible.

The var keyword creates a local variable, local to the current function. Always remember your var keyword. We will look later at additional ways to keep variables private with functions, closure and objects.

Variables a fully Polymorphic

Variables are fully polymorphic, you can store anything you like in any variable, there is no type checking. JavaScript is weekly typed.

var a;
a = 12;
a = "Hello JavaScript!";

This is different to a language like Java where variables can only store one type of thing.

Having weekly typed variables is appropriate for JavaScript. It allows our scripts to be much shorter as we don't have to write any code to get around the type system. Shorter scripts means faster downloads.

However weak typing makes it harder for large teams to work together, and it makes it hard for an IDE to do code completion. It's a trade off.

Exercise - Weeks in a lifetime

Given three variables

var daysInYear = 365.25;
var daysInWeek = 7;
var yearsInLifetime = 80;

Calculate the average number of weeks in a human lifetime.

Strings

Strings in JavaScript are arrays of characters. You define them using single or double quotes, as long as you are consistent:

"Hi there";
'Hi there';

We can include escape characters in strings with a backslash:

"Hi \n there";
"Hi \"there\"";

Most styleguides prefer single quoted strings because they use fewer pixels and thereforemake your laptop weigh less in your bag. (Just kidding about that last part.)

Concatenation

You can concatenate strings using the + character:

"Hello " + "There";

Strings as arrays

Strings work rather like arrays. Access a part of a string using the square brace syntax like so:

"Hello there"[0]; // returns "H"

Note that although strings look like arrays, they are not arrays, and don't give you the array API.

Handy functions

You can split a string into an array using the split function:

"Hello".split('');
// ['H', 'e', 'l', 'l', 'o']

You can join the array back up again using the join function:

['H', 'e', 'l', 'l', 'o'].join('')
// "Hello"

If you want to reverse a string you can split it, reverse the array, then join them back together again:

"Hello".split('').reverse().join('');
// "olleH"

You can replace a value in a string using the replace function:

"Hello".replace('e', 'a');
// "Hallo"

You can also use a regular expression:

'Hello'.replace(/l/g, 'w');
// "Hewwow"

Exercise - String Concatenation

  1. Create a variable called greeting. Store the value 'hello' in it.
  2. Create a variable called name. Store the value 'world' in it.
  3. Use your variables to alert "hello world"
  4. Use a couple of regex to change the output to "he110 w0r1d"
  5. Use a couple more functions to reverse the result. A coding device! Write the reverse decoder.

Numbers

All numbers in JavaScript are floating point. There are no integers. This keeps things simple for new developers, but you need to be aware of this if you are writing code to deal with financial transactions.

Typically it's not an issue.

Conversion

Convert a string to a number using parseInt or parseFloat:

parseInt("123");

Convert a number to a string simply by concatenating it with a string, like so:

"" + 123
"123"

Conditionals

JavaScript comes with conditional statements, if, else if and else:

var a = 12
if (a > 12) {
alert('a was greater');
} else if (a < 12) {
alert('a was smaller');
} else {
alert('a was 12');
}

== or ===?

In most languages == (double equals) means equal to. In JavaScript === (triple equals) means exactly equals to and == means equal to with type casting.

Type casting is fiddly stuff, and often behaves in unexpected ways. Good JavaScript programmers generally avoid ==.

You should use ===.

Exercise - Conditional logic

  1. Create a little program that tells you if it's the morning, afternoon or night. You can get the hour of the day something like this:
// returns a number between 0 and 24
new Date().getHours();

Downloads

Linting with Gulp

Gulp is an essential part of the modern JavaScript toolchain. It handles compilation, linting, concatenation, minification, all as you save.

Here we will use it to automatically lint our files. Any mistakes we make will pop up as we save.

Exercise 1 - Install Gulp

Gulp is built on top of NodeJS, so first install NodeJS from http://nodejs.org. It's a double click install, or you can use your favourite dependency management tool.

Test your installation by typing node at a command line.

node

Exercise 2 - Set up npm

Visit your command line (cmd.exe, terminal or bash). Navigate to the directory where you want to work.

Now initialize npm:

npm init

Exercise 3 - Install gulp and the linter

npm install gulp --save-dev
npm install gulp-cli -g

You may need to restart your console having installed gulp-cli.

Test your installation at a command line by typing gulp.

gulp

Now install the linter

npm install gulp-jshint --save-dev

Exercise 4 - Make a gulpfile

We wire these together using a gulpfile. Create a file called gulpfile.js in the directory where you want to work.

A simple gulpfile.js looks like this:

'use strict';
var gulp = require('gulp');
var jshint = require('gulp-jshint');
// Lint Configuration
var lintConfig = {
"strict": false,
"quotmark": false,
"browser": true,
"devel": true,
"globals": {
"$": true,
}
};
// Files to lint
var files = [
'**/*.js',
'!node_modules/**'
];
// The hint task
gulp.task('js:hint', function() {
return gulp.src(files)
.pipe(jshint(lintConfig))
.pipe(jshint.reporter('default'));
});
// Watch files for changes
gulp.task('watch', function() {
gulp.watch(files, ['js:hint']);
});
// Sets a default task
gulp.task('default', ['watch']);

Have a read through and try to understand the settings. Now go to a command line and type gulp. Any JavaScript files in the directory of subdirectories will be linted.

Exercise 5 - Fix your code

Use the linter to fix all the errors in the intro exercises.

Functions

In JavaScript all functions are objects. You can pass them around, store them in variables and arrays, and pass them as parameters to other functions.

Create a function like this:

function() {
alert('hello function!');
}

This is an unnamed function, sometimes called a lambda expression (really it's just a function without a name).

Functions assigned to variables

Because functions are objects, we can assign them to variables:

var sayHello;
sayHello = function() {
alert('hello function!');
}

This is the normal way of dealing with functions in JavaScript.

Calling Functions

If you save a function in a variable, you can call it using braces like this:

var sayHello = function() {
alert('hello function!');
}
sayHello();

Passing Parameters

Pass parameters to functions between the braces:

var sayHello = function(name) {
alert('hello ' + name);
}
sayHello('Dave'); // alerts 'hello Dave'

If you pass too many parameters, additional ones will be discarded.

sayHello('Dave', 'Mike', 'Dan');
// alerts 'hello Dave'

If you pass too few, unassigned parameters will get the value undefined.

sayHello();
// alerts 'hello undefined'

Exercise - A Sandwich Calculator

  1. Write a function called sandwich calculator. This should accept one value: slicesOfBread
  2. The function should return the total number of possible sandwiches based on the amount of slices available, so if there are 10 slices, it should return 5. Test your function with an alert box.
  3. Extend your function so it accepts two values, slicesOfBread and slicesOfCheese.
  4. It takes two slices of bread and one of cheese to make a sandwich. The function should return the total number of possible sandwiches, so if there are 10 slices of bread, but only 1 of cheese, it should return 1. You'll need an if statement to make this work.

Exercise - Lint your code

Use gulp to lint your code. Fix all the errors.

Closure

Closure can be a tricky concept to get one's head around. It works like this:

  1. Functions are objects and can be declared anywhere.
  2. If I declare a function within another function, the inner function has access to the local variables of the outer function.
  3. Normally when a function exits, all it's local variables are destroyed, but…
  4. If I hang on to the inner function in some way, the local variables of the outer function are still needed by the inner function.
  5. They are still in scope, so they are not garbage collected.

This is closure in a nutshell. Here's an example:

var outer = function() {
var a = "A Local variable"
var inner = function() {
alert(a)
}
window.fnc = inner
}
outer();
fnc();

When we call outer, we define inner and assign it as an attribute of window (in other words, a global variable) inner persists after outer has exited, so the local variable a is still in scope, and still accessible to inner.

Exercise - Try it out

  1. Enter the above code and verify it works.

Self Executing Functions

It seems a bit superfluous to have to call outer to create inner. Outer only exists here to define inner, there's no need for it once inner has been made.

If only there was a way to avoid referencing outer. Thankfully there is.

Here we have a self executing function. The function is in braces, and there are braces at the end. We are declaring an unnamed function, then running it straight away, dispensing with the need for outer.

(function() {
var a = "A Local variable"
var inner = function() {
alert(a)
}
window.fnc = inner
})()
fnc();

Exercise - Guess the output

For each of the following, try to work out what the output will be. Run the code to check your answer.

1.

var a = 12;
(function() {
alert(a);
})();

2.

var a = 5;
(function() {
var a = 12;
alert(a);
})();

3.

var a = 10;
var x = (function() {
var a = 12;
return (function() {
alert(a);
});
})();
x();

4.

var a = 10;
var x = (function() {
var y = function() {
var a = 12;
};
return function() {
alert(a);
}
})();
x();

5.

var a = 10;
var x = (function() {
(function() {
a = 12; // <<< look carefully at this line.
})();
return (function() {
alert(a);
});
})();
x();

6.

var a = 10;
(function() {
var a = 15;
window.x = function() {
alert(a);
}
})();
x();

Further Reading

Read my post on "What is a closure" on Stack Overflow

Exercise - Closure and the Sandwich Calculator

Mrs Potts the school dinner lady is tired of all the global sandwich variables getting under her feet and tripping her up all the time. She needs help cleaning her kitchen. Will you help her?

She would like it very much if you would build a sandwich machine for her, but wrap it in a closure so as to keep everything neat.

1. Create a self executing function

like this:

(function() {
})();

This will be our closure and will hold the sandwich machine, keeping all it's parts nicely together.

2. Create methods

Within the closure, create three little functions to add the bread, spread the soya margarine and add the jam. These little methods should use console.log to write a string representing their action to the DOM, e.g. "Now spreading the jam!"

Assign these functions to private variables, we don't want any of the children breaking in to the closure and spreading jam all over the place.

Now, also within the closure create a makeSandwich function which calls the three other methods in sequence, writing the sandwich instructions to the DOM.

3. Smuggle makeSandwich out of the closure

We want Mrs Potts to be able to call makeSandwich, so we need to make a global variable which she can access from the kitchen, the news agent, a flight to Barbados, anywhere.

Assign makeSandwich to the global window object, thus smuggling it out of the closure. Refer back to the example if you need to remember how to do this.

4. Call makeSandwich from outside the closure

You can now call makeSandwich from outside the closure. Because you've used onDomReady, you'll need to call it onDomReady.

If you've succeeded well done! This is super close to 2016 best practice JavaScript!

Exercise Extension

If you'd like to take this a little further, you could make it receive an array of fillings, then output them in the sandwich.

Arrays and Loops

JavaScript comes with an array of looping constructs. We also have functional style loops which we'll get to soon.

Arrays

We can declare an array using the square bracket syntax, like this:

var a = ["cheese", "ham", "toast"];

Arrays are polymorphic

Arrays are fully polymorphic. You can store anything in them:

var a = [1, "ham", new Date()];

Get the length with .length()

a = [3,6,9]
a.length // 3
a[a.length] // 9

Arrays are not arrays

Arrays in JavaScript are not like arrays in other languages. They are in fact associative arrays, sometimes called hashmaps or hashes.

They have numerical keys associated with arbitrary values.

This means we can create gappy arrays without filling our computer's memory:

var a = [];
a[0] = 12;
a[10000000000] = 13;
alert(a[10]); // undefined

However, don't try to alert the array, or the browser will convert it to a very long string.

You can also store a value in an array with a non-numerical key:

var a = ["cheese", "ham", "toast"];
a['condiment'] = 'ketchup';

While Loops

A while loop will keep going while some condition is true. For example:

var sandwichesMade = 0;
while (sandwichesMade < 5) {
alert("Making Sandwich: " + sandwichesMade);
sandwichesMade = sandwichesMade + 1;
}

For Loop

A for loop is the most efficient type of loop in JavaScript. It looks very similar to classical languages such as C or Java.

people = ['dave', 'jon', 'mikey'];
for (var i = 0; i < a.length; i++) {
alert("Making Sandwich for: " + people[i]);
}

For in loop

We also have a for in loop. This is useful for iterating over gappy arrays with non-contiguous keys:

a = [];
a[0] = "Mikey";
a[12] = "Davey"
a[99] = "Stuey"
for (i in a) {
alert(a[i]);
}

forEach functional style loop

We can also iterate using a functional style loop. A functional loop leaves the iteration implementation up to the object itself. We pass a function to tha array, then the array calls this function for each element. In classical languages we sometimes refer to this as an iterator pattern.

[
'Mikey',
'Stuey'
'Davey'
].forEach(function(el,i){
console.log(el);
});

Exercise - Lunar Countdown

Simple one here. Use the alert function to alert the numbers from 10 down to zero.

When you reach zero, alert "Blast Off!"

Remember to lint your code.

Iterate with a for loop

Assume I have an array of products in my shop, like this:

products = ['Cats', 'Cheese', 'Spanners', 'Lemons', 'Candyfloss'];

Use a for loop to iterate over this and console.log the products.

Extension - Use a functional loop

Repeat the above exercise, but use a functional loop.

Pizza Exercise

Create an array of pizza toppings, like this:

var toppings = ['Cheese', 'Ham', 'Bits', 'Tomatoes'];

Now write a function that we can call like this:

makePizza(toppings);

This function should return a string of the form:

"A tasty pizza with Cheese and Ham and Bits and Tomatoes"

You will find the join function is very helpful here

Harder Exercise - Capitalise every element

Write a short function to capitalise every element of the array.

You must use the Array#map function and the String#uppercase function.

JQuery

JQuery is a standard DOM manipulation tool. It abstracts the browser differences and gives you a clean cross browser DOM API.

Downloads

*Code from the board

The $ function

JQuery gives us just one function, the $ function. The $ function behave differently depending on the parameters we pass it.

We can pass $ another function like this:

$(function() {
alert("Hello from jQuery");
});

This function is a callback. It will be executed when the DOM is loaded. Within it we have access to the DOM.

Selecting element

We can select elements from the page using CSS syntax:

$(function() {
$("p") // this gives us an array of all the paragraphs
});

When we select from the page we get back an array of all the matched elements.

Changing DOM Nodes

We can change the content of the DOM like this:

$(function() {
$("p").html("Hello jQuery");
});

Adding Attributes

We can add attributes to an element like this:

$(function() {
$("a").attr('href', 'http://www.google.com');
});

Styling

We can add styling like this:

$(function() {
$("p").css('color', 'red')
});

Appending

We can append to a DOM node like this:

$(function() {
$("p").append('<strong>Hi from jQuery</strong>')
});

This will append a strong tag to every paragraph.

Exercise - Styling

  1. Use jQuery to select the body element
  2. Use the .css() function to style the body. Give it a red background and blue text.

Exercise - Changing the DOM

  1. Use jQuery to select the body element
  2. Use the .html() function to change the body text. Replace the DOM with a new one.

We can completely rewrite our page.

Exercise - Append

  1. Use jQuery to select the body element
  2. Use the .append() function to append a new hyperlink.
  3. Use the .attr() function to set an href attribute on the hyperlink. Open it in your DOM and check it's clickable.

We can add elements to our DOM.

JQuery Events

The real strength of JavaScript is that it allows the page to respond to the user. Whenever the user does something on the page, from moving the mouse to pressing a button, to submitting a form, lots of little events are fired off in the browser. We can tell our code to listen for certain events and call functions in response to them.

Assume a little div like this:

<!DOCTYPE html>
<html>
<head>
<title>jQuery</title>
<script src="jquery.js"></script>
<script src="dont_click.js"></script>
</head>
<body>
<div class="clickable">
Do not press this button.
</div>
</body>
</html>

We can write some corresponding JavaScript to find the clickable element and assign a function to the click event.

$(function() {
$(".clickable").click(function() {
alert("I can't believe you just did that!");
});
});

Deconstructing don't click

Let's just deconstruct that JavaScript a little and have a look inside.

First we have this:

$(function() {
...
});

This calls the dollar function and passes it a function. When we pass dollar a function, jQuery puts it on one side until the DOM is loaded and runs it then. jQuery

The function we passed it looks like this:

$(".clickable").click(function() {
...
});

Can you guess what it does? First it gets all the elements on the page with class "clickable". Then it calls a method called click on them. This method says what to do when we click. It's a click handler.

And what happens when we click it? This happens:

alert("I can't believe you just did that!");

…and we get our cute little alert box. So appealing!

Exercise - Make it red

  1. Create a web page with half a dozen paragraphs on it.
  2. Add a click handler. When you click a paragraph it goes red.

Exercise - Keyup

Create a text input field. Listen for the keyup event. Alert the value of the text box whenever keyup occurs.

Get the value of an input field using:

$('input').val();

For bonus points, append the value of the text box into a div.

Further Exercise - Rollover

  1. Review the list of events on: http://api.jquery.com/category/events/
  2. Create code that listens for a hover event. When the user rolls over a div, place the word "over" in that div.
  3. When the user mouses out of the div, place the word "out" in the div.

Further work

Count the total number of rollovers and output that in a div.

Downloads

Each Peach

JavaScript comes with all the looping constructs you would expect, for, while, etc. The work as you would hope, and I'm not going to go into these here.

Functional loops

Because JavaScript is a functional language, there are many libraries that allow you to use functional style loops.

A functional loop is one where you pass in a lambda function. The looping function then takes care of supplying values to the lambda function one at a time.

JQuery each

JQuery selectors return an array of DOM nodes. This means that with a single selector, you can pull out all the paragraphs on the page, or all the hyperlinks with a particular class. When we apply methods to a jQuery object, we are generally working on all of the DOM nodes at the same time. This is part of the power of jQuery. For example.

$('p').hide();

…will hide every single paragraph on the page without exception. It applies hide to all paragraphs. The selector returns all the paragraphs as an array of DOM nodes, then the hide method iterates over all of the paragraphs, hiding them.

A selector may return just one DOM node, and this is fine, but it will still return it in an array with just one item:

$('.page_header h1')

…will likely only match one item on the page, but it is still returned in an array. This common interface makes things very simple for us, provided we want to do exactly the same thing to every matched DOM node, but what if things aren't so simple.

Iterating with Each

What if we want to treat each element as a special case. What if we want to do a different thing to each element.

Fortunately, jQuery gives a really simple way to iterate over our elements one at a time using the .each function. .each accepts a function, and then applies the function to the nodes one at a time, passing in the node itself as "this".

Here we use each to create the beginnings of an image gallery:

HTML

<!DOCTYPE html>
<html>
<head>
<title>Each</title>
<script src="jquery-1.5.js"></script>
<script src="each.js"></script>
</head>
<body>
<img src="kitten.jpg" alt="kitten" />
<img src="puppy.png" alt="puppy" />
<img src="lemur.gif" alt="lemur" />
</body>
</html>

This HTML file contains three images, each of which has an alt attribute. For each image, we're going to pull out the alt attribute, pop it in a span, and put that after the image.

JavaScript - each.js

$(function() {
$("img").each(function() {
var img = $(this);
var alt_text = img.attr('alt');
img.after("<span>" + alt_text + "</span>");
});
});

Here we select every image on the page, then iterate over the resulting array using each. Each receives a function, and the function has access to the DOM node via the "this" variable. We convert "this" into a jQuery object, pull out the alt text, then append the alt text after the image.

Each Peach Exercises

We use the each to iterate over a jQuery object, performing an action on each one in turn. Lets try that now

Exercise - A big mess

You can generate a random integer between 0 and 500 using the following code:

Math.random() * 500

You can generate a jQuery object that contains everything on the page inside the body element like so:

$('body *');

Write a jQuery function that iterates over everything on the page using each, makes them all position:absolute, and assigns random top and left values. You need to use each here to give them all different random values.

Further Exercise

Assume you want to put email addresses on the Internet, but you want to keep them hidden from automated spam bots.

Rather than write your email as a link like this:

<a href="mailto:hello@example.com">hello@example.com</a>

You instead choose to obfuscate it like this:

<span class="email">hello at example dot com</span>

Use your knowledge of JQuery to rewrite the span as a clickable mailto hyperlink.

Put multiple different emails addresses on the page. Use the each method to ensure the code works for every email address on the page.

Manipulating the string

Note that you can use "string".replace('val', 'replacement') to replace values in a string.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

Object Orientation with JSON and Mario Exercise

Downloads

Welcome to JSON

There are several different syntaxes for declaring objects in JavaScript. Of these, the cleanest and most commonly used is JavaScript Object Notation (JSON), pronounced Jason.

Packaging our code up into JSON gives us several significant advantages:

  1. It looks pretty.
  2. It reduces the number of objects in the global namespace.
  3. It's great for AJAX, smaller than XML and readily parsable both client and server side.

In this series of exercises we'll write some JSON, create an API and finally add a thin layer of listeners to hook it up to a jQuery User Interface.

JSON looks like this:

var mario = {
description:"Small and jumpy. Likes princesses.",
height: 10,
weight: 3,
speed: 12
}
var bowser = {
description: "Big and green, Hates princesses.",
height: 16,
weight: 6,
speed: 4
}

Here we have defined two objects, one called mario and on called bowser. As you can see, they consist of a series of name value pairs. We can access the values like so:

alert(mario.description);

We can modify values like so:

mario.description = "Big and smashy, having eaten a mushroom"

We can even add new attributes like so:

mario.can_fly = true;

Objects are useful for keeping things neat and tidy. We have encapsulated all the information about Mario in a single place so it's easy to get at and understand.

Exercise - canFly

  1. Enter the above code
  2. Alert the values of mario.description and bowser.description
  3. Use your web inspector to add a breakpoint. Check the values of the JSON objects in the debugger.
  4. Add a canFly attribute to Mario using the dot syntax. Again, check the debugger.
  5. Create an entry for Luigi. He's a bit thinner that Mario, but slightly taller, and he wears a green outfit.

A Rather Dull Mario Game

If we wanted we could write a little Mario game using these objects. Lets create a little function to see who wins in a boss battle:

var boss_battle = function() {
if (mario.speed > bowser.speed) {
alert("Mario has escaped and saved Peach");
} else {
alert("Bowser has stomped all over Mario. Mario is dead.");
}
}
boss_battle();

As we can see, Mario wins. Let's swing the odds a little in Bowser's favour. Bowser can go into a powered up mode where he swoops from side to side on the screen. We'll call this Bowser Boost.

Let's extend our game a little to add Bowser Boost:

var mario = {
description:"Small and jumpy. Likes princesses.",
height: 10,
weight:3,
speed:12
}
var bowser = {
description:"Big and green, Hates princesses.",
height: 16,
weight: 6,
speed: 4,
boost: 0
}
var boss_battle = function() {
if (mario.speed > bowser.speed + bowser.boost) {
alert("Mario has escaped")
} else {
alert("Bowser has stomped all over Mario")
}
}
boss_battle();
bowser.boost = 20
boss_battle();

Exercise Invincible

  1. Enter the above code and get it to run. Who wins?
  2. Give Mario an invincibility attribute. If invincibility is true, Mario always wins. Unfair I know.

Don't worry, we are going somewhere with this. Next!

Lets clean this code up a little

  1. Add two more attributes to each character: attack_power and name.
  2. Extend the boss battle function so it receives two parameters, contestant_1 and contestant_2.
  3. Rewrite it so that instead of running the conditional, it simply prints out the name of the contestant with the highest attack_power. This renders all the other attributes irrelevant, it only checks the attack_power.

Functions within JSON

This is all very well. We have Mario and Bowser objects and a function to compare them, but it seems a little artificial having all our functions scattered all over the place like this. Also, the more functions we have in our global namespace, the more likely it is that they will conflict, and we'll accidentally overwrite something important.

Let's see if we can improve things.

var mario_world = {
mario: {
name:"Mario",
description:"Small and jumpy. Likes princesses.",
celebration: "Mario wins and does a little dance",
height: 10,
weight:3,
speed:12,
attack_power: function() {
return this.weight * this.speed;
}
},
bowser: {
name:"Bowser",
description:"Big and green, Hates princesses.",
celebration: "Bowser wins and does a big roar",
height: 16,
weight: 6,
speed: 4,
boost: 0,
attack_power: function() {
return this.weight * (this.speed + this.boost);
}
},
boss_battle: function(contestant_1, contestant_2) {
alert(contestant_1.name + " vs " + contestant_2.name);
if (contestant_1.attack_power() > contestant_2.attack_power()) {
alert(contestant_1.celebration);
} else {
alert(contestant_2.celebration);
}
}
}
mario_world.boss_battle(mario_world.mario, mario_world.bowser);

Ah, that's better. As you can see, this entire program is encapsulated within a single object called mario_world. The mario_world object is the only object in the global namespace. the boss_battle function is now an attribute of mario_world, and each contestant has an attack_power function that works out his strength in a battle. The boss_battle function is parameterised, so you can battle any contestant against any other.

We have also written an attack_power function which is implemented by bowser and mario. This calculates the attack power from a series of other parameters.

Because functions are objects, we can assign them as attributes of objects. They're key value pairs, but if you've programmed before, you'll notice they work like methods. We can now call methods on our JSON objects.

What is this?

You might have noticed also that in the attack_power function we use the "this" keyword. We say this.speed and this.boost.

This is a troublesome keyword that trips up even quite advanced JavaScript developers all the time. "this" refers to the context in which the code is currently operating in. In this case, the context is mario (or bowser) and so this refers to these variables. That's because the attack_power function is an attribute of mario. This points to the object the current object is a member of. Your knowledge of JavaScript will be measured by your understanding of scope, and the "this" keyword, so we'll come back to this, but for now, let's make a real game…

Exercise - Princess Peach

  1. Enter the above code and make it work.
  2. Add Princess Peach. The princess is smaller and lighter but compensates for this by being quicker and having a dash mode. Battle Peach vs Bowser and Peach vs Mario.
  3. Add an activate_boost function to Bowser that adds 5 to his boost. You should be able to call mario_world.bowser.activate_boost.
  4. Add a toggle_dash function to peach. Calling it should activate or deactivate her dash attribute.
  5. Just for kicks, change the boss battle function so instead of outputting alerts, it returns a string. Now we have an API.

But what about the User Interface?

Having defined our API, it's now time to hook it up to a user interface. This is where jQuery comes into it's own.

  1. Extend your HTML page. Create a form. Add two dropdowns, containing the names of the available characters. Ideally populate these dropdowns by querying the API. You may need to adjust your JSON to do this.
  2. Add a "Fight" button that will make those two characters battle.

Further Challenge

Now lets take things a little further. I'll leave this up to you.

  1. Add a button for Bowser Boost. When you click it, his boost is increased.
  2. Add a Peach Dash button. Every time you click it, Peach's dash mode is toggled on and off.
  3. Make it so that when the dash and boost buttons are only visible when Peach or Bowser are selected.
  4. Handle the case where the battle is a draw.
  5. Grab images for each character. Store the URL of the image in the JSON. Draw an arena and put the characters in it when they are selected.
  6. Destroy the losing character with an appropriate animation.
  7. When the fight button is clicked, animate a fight briefly before destroying the loser.

Downloads and sample answers

You can find sample answers in the Dropbox here.

Object Orientation

You may have noticed JavaScript doesn't have classes. In fact, as we have seen with JSON JavaScript doesn't need any of that to make an object, but without classes we do lose a few pieces of functionality, specifically:

  • Constructor functions
  • Inheritance

In fact we don't lose any such functionality. Because there are no classes, we are free in JavaScript to use any object as the parent of another object.

We can also use any function as a constructor function.

Constructor functions

Constructor functions are just regular functions. By convention we capitalise them, like this:

var Toaster = function() {};
var CheeseDip = function() {};

We then create a new object using this function with the new keyword:

var myToaster = new Toaster();
var myCheeseDip = new CheeseDip();

In our Toaster function we can initialise the toaster by writing to the 'this' variable, which in the context of a constructor will be set to point to the object under construction's prototype.

var Toaster = function() {
this.goPing = function() {
alert('ping');
}
this.toastQuotient = 2;
};
var myToaster = new Toaster();
myToaster.goPing();

Exercise - Constructor Functions

Make me a little car (or choose your own domain). The car should have a latitude and longitude attributes. It should have goNorth, goSouth, goEast and goWest functions. It should have a toString method that prints the current location.

Now go for a drive.

Prototypical inheritance

Most classical languages have classes which inherit from one another. Objects are then instances of classes. JavaScript has no classes, so objects inherit directly from other objects, which when you think about it is quite sensible.

We talk about an object's prototype. The prototype is the object which our new object will inherit from.

Here's a cut down example, we're just inheriting from a humble JSON object called x.

var x = {y:'z'}
var A = function() {}
A.prototype = x;
a = new A();
a.y; // 'z'

Here's a more practical example. This time our Toaster inherits from an instance of Appliance.

Notice we inherit from an object, not from the constructor function.

var Appliance = function() {
this.goPop = function() {
alert('pop');
}
};
var Toaster = function() {
this.goPing = function() {
alert('ping');
}
this.toastQuotient = 2;
};
Toaster.prototype = new Appliance();
var myToaster = new Toaster();
myToaster.goPing();

Prototypical inheritance Exercise

Create a Vehicle constructor to be a parent of the Car. Move your functions and attributes up into the vehicle.

Now create a new Car, it should still be able to drive.

Add a new method to the car, so we can change the oil.

Now make a bike object which also inherits from Vehicle and instantiate it. Very nice.

Object.create

ES5 gave us a new Object prototype method designed to make inheritance easier.

var appliance = {
goPop: function() {
alert('pop');
}
};
var toaster = Object.create(appliance)
toaster.goPing = function() {
alert('ping');
}
toaster.goPop();
toaster.goPing();

Object.create lets us create a child of any other object. The prototype chain can be as long as you like.

Exercise - Object.create

Re-implement your car using object.create. Be sure to keep you old version around somewhere.

Composition

Because objects in JavaScript are just associative arrays, we can compose an object from parts of another object without using inheritance just by copying attributes from one to another.

var toaster = {
goPing: function() {
alert('ping');
}
};
var cheeseWhizMachine = {
goPing: toaster.goPing
}
cheeseWhizMachine.goPing()

We can use this to implement a decorator pattern:

var pingDecorator = {
decorate: function(obj) {
obj.goPing = function() {
alert('ping');
}
}
}
var cheeseWhizMachine = {};
pingDecorator.decorate(cheeseWhizMachine);
cheeseWhizMachine.goPing();

Composition Exercise

Create a navigation decorator that will decorate any object with goNorth, goSouth, etc methods.

Optional Extra JQuery Exercise

If you finish first, create a driving simulator.

There should be 4 buttons, up, down, left and right. Use JQuery to draw the car on the screen and wire up the buttons. Use CSS to absolutely position it. Use the buttons to update its top and left values.

Further Reading

The MDN developer docs have a good write up of all of this here: Inheritance and the prototype chain

This

This is a special variable in JavaScript. It is instantiated when you call a function,and it's value will change depending on how you call the function.

This in the global scope

If we open a console and simply type this, we get back "window".

console.log(this)
//Window

The default value for this is the global scope. If we do nothing else, this will be the global scope.

This within a function

Likewise, the value of this within a global function will also be the global scope:

var a = function() {
console.log(this);
}
a();
// Window

This in an object

If we are calling a function as an attribute of an object, this is set to that object. This is always the object we are operating inside of.

The simple heuristic is that this is the object immediately preceding the dot.

var car = {
speedUp: function() {
console.log(this);
}
}
car.speedUp();
// outputs the car
var speedUp = car.speedUp;
var speed = 0;
speedUp();
// outputs the global scope object Window
var bus = {
speedUp: car.speedUp
}
bus.speedUp();
// outputs the bus

This in a closure

People often confuse this. The value of this is related to JavaScript as an object oriented language. It is not affected by the closure.

var fnc = function() {
var inner_fnc = function() {
console.log(this)
}
inner_fnc();
}
fnc();
// Window

Setting this with apply

We can also manually set the value of this to any value we like. This trick is employed by several frameworks to make your life easier.

For example, jQuery will set the value of this to be the DOM node that received an event. Angular will set the value of this to the controller when you call a function on that controller's $scope object.

var myFunc = function() {
console.log(this);
}
var myObj = {
test:"cucumbers"
}
myFunc.apply(myObj,[]);
// outputs myObj

Exercises - Guess the Value of This

Question 1

var x = function() {
console.log(this);
};
x();

Question 2

var x = {
y: function() {
console.log(this);
}
}
x.y();

Question 3

var x = function() {
console.log(this);
}
var y = {
x: x
}
y.x();

Question 4

var x = {
y: function() {
console.log(this);
}
};
var a = {
b:x.y
};
a.b();

Question 5

(function() {
var x = function() {
console.log(this);
}
x();
})();

Question 6

(function() {
var x = function() {
console.log(this);
}
y = {};
y.x = x;
y.x();
})();

Question 7

(function() {
var x = function() {
console.log(this);
};
x.apply({a:'b'});
})();

Question 8

(function() {
var Cat = function() {
console.log(this);
};
var x = new Cat();
})();

Exercise - Fix the broken code

The following code is broken. There are a few ways it could be fixed, we are going to fix it by storing the value of "this" in a variable which we will call "that".

$(function() {
var ui = {
init: function() {
$('a').click(function() {
this.showSpinner();
this.getContent();
});
},
showSpinner: function() {
console.log('spinning');
},
getContent: function() {
console.log('getting that content');
}
}
ui.init();
});

AJAX

AJAX is the amazing space age technology that allows you to transfer data to and from your server direct from JavaScript, updating it in real time without any need for a page refresh.

This is enormously cool.

A Misnomer

AJAX stands for Asynchronous JavaScript And XML, but it's actually something of a misnomer, since we seldom use XML any more. More commonly we will find ourselves using JSON, or HTML fragments.

Unfortunately, AJAJ is not a great acronym, and AJAH sounds like a door, so we're stuck with AJAX for now (which has the nice side effect of making us sound cool and awesome).

Talking to the server using jQuery

We typically use a wrapper function to help us with AJAX. In this exercise, we will use jQuery as a wrapper around the XMLHttpRequest object. We will get greater cross browser compatibility, and a nice syntax which hides the rough edges.

When performing an AJAX request using jQuery, we have a number of wrapper functions to call on.

$.ajax

$.ajax is the most flexible. It allows us to perform an XMLHttpRequest with a nice syntax. We can easily assign callbacks to each stage of the process, and can perform any type of request.

$.getJSON

$.getJSON is less flexible. It allows us to pull a json object, which is automatically converted to a JavaScript object which we have access to. Powerful in it's simplicity.

Documentation

The jQuery AJAX api is available here:

http://api.jquery.com/category/ajax/

Easy In AJAX Exercise

Let's start slow…

This exercise is in four parts. See if you can follow along.

Part 1 - Make the HTML

First create a little html file containing a little bit of text and upload it to the server. Verify that you can indeed see the file by viewing it in a web browser.

Part 2 - Do the AJAX

Now write a Javascript file that hits that URL (note, the url will need to be local to the file, so no http:// at the start):

var url = "myfile.html"
$.ajax(url);

Use the Firebug console to verify that the file is being downloaded. Brilliant, you're doing AJAX!

Part 3 - Listen for the result

Next add a lister. We're going to listen for 'done', so…

$.ajax(url).done(function(data) {
  alert(data);
});

This function is called when the ajax request completes successfully. Wow, you have AJAX.

Part 4 - Do something with the result

Finally we want to do something with the result. Lets just append it to the body.

$.ajax(url).done(function(data) {
  $('body').append(data);
});

Et voila. We have called the ajax, listened for the result, and finally added the result to our page. Note that we don't need to just add the result to the page, we could do something else with it instead. For example we could put it into a particular div, make it pop up, or just use it for something else.

Jolly well done.

Exercise - Flickr

You can Pull a Flickr image feed from the following URL:

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?

You can pull this feed using a call like this:

$.getJSON(url).success(function() {
// write the feed to the DOM here...
});

Pull the feed, then for each image, render the image and draw it to the DOM.

Further Exercise - HIJAX

Overriding the function of hyperlinks is a useful thing to be able to do. The hyperlink will work normally in the absence of JavaScript but will AJAX in the content if it is able. This technique is sometimes rather cleverly called HIJAX.

  1. Add a list of hyperlinks to a page. When a hyperlink is clicked, detect that event, and call a function that retrieves the content via AJAX and inserts it into an element on the page.

Further Work

  1. Add a data attribute to some of your links data-remote="true" now add the event only to hyperlinks with this data-attribute, so only links with data-remote set will use AJAX.
  2. Add a spinner. link is clicked, display a little spinner next to the link to show something is happening. the complete event occurs, remove the spinner.
  3. Add caching. Add a data-section-id attribute to your hyperlinks. When you click a link, first check for the presence of a div with that id. If it is present, reveal it. If not, create it, ajax the content into it, hide any other divs that may be on the page, and reveal the div that you just created. Fun!

Lodash Templates

We can improve our front end using templates. Templates are strings, potentially take from the DOM, which can be compiled against an object to produce a new DOM node

LoDash (a fast implementation of underscore) provides one such implementation.

First we must include loDash on our page using a script tag: https://lodash.com

Then we create a template as a string and compile it against an object

var template = _.template("Hello {{ name }}!");
var compiledTemplate = template({name: "World"});
// Outputs: "Hello World"

Pulling the template from the DOM

We don't want to be writing templates as strings in our JavaScript. Ideally we compose HTML in our HTML. The most convenient way to do this is with a script tag.

We set a type of text/template to prevent the browser from trying to execute the template as JavaScript. We set an id attribute to allow us to find the template.

<script type="text/template" id="helloTemplate">
"Hello {{ name }}!"
</script>

We can then write some JavaScript:

$(function() {
var templateStr = $('#helloTemplate').html();
var template = _.template(templateStr);
var compiledTemplate = template({name: "World"});
})

Exercise - Mario

Extract your Mario UI into a template.

Harder Exercise - A Flickr feed

Improve your Flickr app.

Create a template which renders a single image from the feed, now use lodash to pull this template from the DOM and, for each image, render the image and draw it to the DOM.

Promises

Promises are now a core feature of JavaScript, and are available in Chrome and Firefox. This is interesting news.

What is a promise?

JavaScript is single threaded, but it needs to deal with asynchronous events. In the past we used callbacks for this. Say we wanted to make an AJAX request, we might pass a callback in like this:

var url = '/mydata.json';
$.getJSON(url, function(data, status) {
if ((status) == '200') {
// update the page;
} else {
// alert the user
}
});

This is fine if we need to do only one thing, but what if we need multiple things to wait for each other? Now we have callbacks within callbacks within callbacks. Our code becomes a callback Christmas tree. A deeply nested triangle of code decorated with behaviour.

More recently we got the ability to write code like this (again jQuery):

var url = '/mydata.json';
$.getJSON(url)
.done(function(data) {
// update the page;
})
.fail(function(){
// alert the user
});

This is a nicer pattern. We have smaller functions, each of which does a single thing, and the conditional is gone.

The call to $.getJSON(url) returns a promise of future data, a Promise. We can chain methods off it to deal with the success and error states.

Promises are a formalisation of this syntax. We get standardised method names and parameters, which makes it easier to make libraries interoperate with one another.

Promises are now core JavaScript

A variety of Promise specifications and libraries have been produced over the last few years. Fortunately we now have an official specification.

We create a promise like this:

var getA = new Promise(function(resolve) {
var a = 12;
resolve(a);
});

We can then have something happen when the promise resolves:

getA
.then(function(a) {
console.log(a);
});

Chaining thens

We may wish to have multiple things happen when our promise resolves. If our thenned function returns a value, that value will be passed on down the chain, like so:

var getA = new Promise(function(resolve) {
var a = 12;
resolve(a);
});
getA
.then(function(a) {
console.log(a);
return a + 1;
})
.then(function(b) {
console.log(b);
return b + 1;
})
.then(function(c) {
console.log(c);
});

If the function returns a value, the next element in the chain is called right away, but if a thenned function returns a promise, we wait until it is resolved. This can happen anywhere in the chain.

var getA = new Promise(function(resolve) {
var a = 12;
resolve(a);
});
getA
.then(function(a) {
console.log(a);
return a + 1;
})
.then(function(b) {
console.log(b);
// This promise won't resolve for 1000ms
return new Promise(function(resolve) {
setTimeout(function() {
resolve(b + 1);
}, 1000)
});
})
.then(function(c) {
console.log(c);
});

Creating a promise which has already resolved

This code is not cool:

var getA = new Promise(function(resolve) { resolve(); });

I've done this solely for the purpose of creating a promise object which I can chain from. We can create a promise which is already resolved like so:

var sequence = Promise.resolve();

When a promise is in the resolved state, any thennable functions fill be executed right away in sequence.

sequence
.then(function() {
console.log("First")
})
.then(function() {
console.log("Second")
})

We can then make use of this promise to chain sequential code.

Thenning regular functions

This means that any function which receives a value and returns one can be integrated into the chain. For example parseInt:

var getA = new Promise(function(resolve) {
var a = "12";
console.log(a + a); // outputs "1212"
resolve(a);
});
getA
.then(parseInt)
.then(function(a) {
console.log(a + a); // outputs 24
});

Catch

It may be the case that our promise fails to resolve. Perhaps our AJAX request fails. Perhaps our API is down. Perhaps there is no database. Perhaps we timeout.

In these instances we might need to reject the promise. We can do this like so:

var getA = new Promise(function(resolve, reject) {
reject('Sorry, there was no A');
})

We can then catch the error like so:

getA
.catch(function(reason) {
console.log(reason);
});

If a promise is rejected, we skip any intervening thens, and go right to the catch, then we continue as normal.

var getA = new Promise(function(resolve) {
resolve();
});
getA
.then(function() {
console.log('one');
return new Promise(function(resolve, reject) {
reject("There was a problem!");
});
})
.then(function() {
console.log('two');
// This function will not be called
})
.then(function() {
console.log('three');
// Nor will this one
})
.catch(function(error) {
// We skip right to this one
console.log(error)
})
.then(function() {
console.log('four');
// This function will be run
})

Note that if your code throws an exception, the promise will be implicitly rejected and execution will proceed to the next catch block.

Promise.all

Sometimes we might want to wait until all our promises have resolved before we execute the next step. For this we have Promise.all.

var waitAWhile = new Promise(function(resolve) {
setTimeout(function() {
console.log('waited a while');
resolve('a');
}, 1000);
});
var waitAWhileMore = new Promise(function(resolve) {
setTimeout(function() {
console.log('waited a while more');
resolve('b');
}, 2000);
});
Promise.all([
waitAWhile,
waitAWhileMore
]).then(function(a) {
console.log(a, 'done waiting'); // output ['a', 'b'] 'done waiting'
});

The thenned function will receive an array of return values from the functions.