JavaScript Essential Training

LinkedIn Learning : Morten Rand-Hendriksen

Functions and Objects

Functions in JavaScript

There are three types of function in JavaScript.

The structure of a function is fairly standard. It starts with the keyword, function, followed by the function name and any arguments in parentheses. The body of the code is enclosed in curly braces.

As an example, let’s say we want to create a function called multiply which takes two numbers as arguments and returns the result of multiplying the numbers together. The function will look something like this.


		1.	function multiply (a, b)  {
		2.		var result = a * b;
		3.		console.log(result);
		4.		return result;
		5.	}
	

Figure 30 - an example of a function in JavaScript

The function can be called simply with its name followed by he parentheses and any arguments.


		multiply (7, 9);
	

Since the script doesn't execute until it is fully loaded, it doesn't matter where the code for the function goes in the script, but it is generally considered to be good practice to put the function definition before the function call. This is more logical and therefore a little easier to read.

Build a Basic Function

Let's say we want to build a function that compares two fractions and tells us which of the two is larger. We will start with an empty script file and create the outline of our function as follows.


		1.	function findBiggestFraction() {
		2.	  console.log("The function is running!");
		3.	}
		4.	 
		5.	findBiggestFraction();
	

So that gives us the basic function although at the moment, the only thing it does is log a message to the console to let us know it is running. Note that there are no arguments yet, but we do need to include the empty parentheses when calling the function.

Inside the function, we will use a ternary operator that compares the two (actually, it checks whether the first argument is larger and logs a message to the console with the value of the first argument, if it is larger, or the value of the second argument if it isn't.


		a > b ? console.log("a: ", a) : console.log("b: ", b);
	

We can then add a couple of lines to our script to create appropriate variables and use the to call the function. Our script now looks like this.


		1.	function findBiggestFraction() {
		2.	  a > b ? console.log("a: ", a) : console.log("b: ", b);
		3.	}
		4.	 
		5.	var a = 3/4;
		6.	var b = 5/7;
		7.	 
		8.	findBiggestFraction();
	

If we run this, we see the output


		a: 0.75
	

This might look a little strange. We are not actually passing any values to the function. Rather, we are creating variables, a and b, which have global scope and accessing these inside the function.

To illustrate this, we can put a statement in the function that manipulates one of the values and then output that value to the console after the function call has been made. Our script will now look like this.


		1.	  function findBiggestFraction() {
		2.	    a > b ? console.log("a: ", a) : console.log("b: ", b);
		3.	    a = 1000;
		4.	  }
		5.	 
		6.	  var a = 3/4;
		7.	  var b = 5/7;
		8.	 
		9.	  findBiggestFraction();
		10.	  console.log(a);
	

Figure 31 - the script with our findBiggestFraction() function amended to show that it is using global variables, not variables passed to the function

When we run this, we see the output shown below.

Figure 32 image

Figure 32 - the output we get when we run the code shown in figure 31

We can see that a new value has been assigned to a inside the function and logged to the console outside the function. It is possible that the course will go on to explain that this is bad, but this is, indeed, a bad way to write a function! Admittedly, this might make more sense if the function were more complex and/or called more frequently.

A more sensible way, in my opinion, is to write the function like this.


		1.	  function findBiggestFraction(a, b) {
		2.	    a > b ? console.log("a: ", a) : console.log("b: ", b);
		3.	    a = 1000;
		4.	  }
		5.	 
		6.	  var f1 = 3/4;
		7.	  var f2 = 5/7;
		8.	 
		9.	  findBiggestFraction(f1, f2);
		10.	  console.log(a);
	

Figure 33 - the findBiggestFraction() function re-written to use arguments

This looks a little more reasonable. We are creating the function using two formal parameters, a and b. Outside of the function, we are creating two new variables, f1 and f2, and passing these to the function. The function isn't returning anything, it is just outputting the larger of the two fractions.

The output from running this is shown below.

Figure 34 image

Figure 34 - the output we get when running the code shown in figure 33

We get the same output here as we did when we ran the code previously (that is, a: 0.75). We also get an error because I kept the code that amends the value of a inside the function and logs it to the console after the function has been called.

The error message shows that there is an undefined variable on line 10.

There is no problem with JavaScript manipulating the value of a inside the function because a is one of the functions formal parameters. But we can’t access it outside the function, hence the error.

Adding Arguments

As I expected, the course video covered the better way of writing a function I described in the previous section. I'm not sure why they bothered with the notion of using global variables inside a function because, yet it does work but it really does so by violating a number of good programming practices and as such, it really shouldn't work.

However, it is always important to remember that when you are learning a programming language, you are not just learning how to write code, you are also learning how to read it. Since JavaScript does allow you to write a function like this, it is possible you may see code written like this so it is useful to know that this will work and also, why it works.

It's also good to know why it is bad and this is firstly because the function is effectively not reusable, but also, more importantly, it is creating variables used both inside and outside the function and this violates the idea of a function as a black box. If a function may change the value of a variable that exists outside of the function, you really do need to know what happens inside the function!

Return Values from a Function

We can rewrite our function so that it returns a value rather than displaying a result. To do that, we will create a variable in the function which we will call result.


		var result;
	

We will also modify the ternary operator so that rather than display the largest fraction to the console, it assigns a value to result. This value will be an array which contains two elements. The first is a string containing a name for our fraction ("firstFraction" or "secondFraction") and the second is a number which is the value of the fraction.

If a > b, the name of our fraction will be "firstFraction" and the value will be a. If not, the name will be "secondFraction" and the value will be b.


		a > b ? result = ["firstFraction", a] : result = ["secondFraction", b];
	

The result is returned with a simple return statement.


		return result;
	

When we call the function, it won't do anything other than return a value, so if we want to make use of this, we need to use the value outside the function.

One way to do that would be to use something like console.log with a call to the function like this.


		console.log(findBiggestFraction(firstFraction, secondFraction));
	

The function returns an array and this array is passed to console.log, so this is what we see in the output.

Figure 35 image

Figure 35 - outputting the value returned by the function

If we want to do more with the value returned, we can assign it to a value.


		var fractionResult = findBiggestFraction(firstFraction, secondFraction);
	

We can then output the result as an array as we did in figure 35, but we can also access the individual element of the array in order to format our output.


		1.	console.log("First fraction result: ", firstFraction);
		2.	console.log("Second fraction result: ", secondFraction);"
		3.	console.log("Fraction " + fractionResult[0] + ", with a value of " + fractionResult[1] + " is the bigger fraction"); 
	

The output from this is

Figure 36 image

Figure 36 - the output from our function showing that we can work with the returned value

Anonymous Functions

Anonymous functions are possibly more common that named functions in JavaScript, so we will re-write the previous example, the findBiggestFraction() function, as an anonymous function.

Bear in mind that an anonymous function doesn't have a name so we can't call it in the conventional way. We will have to tie it to a variable name or an event, for example.

We will start with an empty script file and create two variables.


		1.	var a = 5/7;
		2.	var b = 18/25;
	

We will then create a variable and tie it to our anonymous function, like this


		1.	var theBiggest = function() {
		2.	  var result;
		3.	  a > b ? result = ["a ", a] : result = ["b ", b];
		4.	  console.log(result);
		5.	} 
	

In effect, we are assigning the function to a variable in a similar way to assigning a value, so the function goes on the right of the = sign. It looks pretty much like the type of function we saw earlier, but since it is an anonymous function, we haven't given it a name.

What we have done is to assign a function expression to the variable to our variable, theBiggest. This is, I guess, similar to assigning the result of an arithmetic expression such as


		sum = a + b;
	

so the net effect is that we are kind of setting the value of theBiggest to be the result of executing the anonymous function. That's not quite true, because we don't execute the code at this point. In order to use the anonymous function, we simply reference the variable, but we add parentheses to the variable name.


		theBiggest(); 
	

Bear in mind that in this version of the script, our function isn't returning anything. To illustrate this, let's quickly look at what the script looks like at this point.


		1.	var a = 5/7;
		2.	var b = 18/25;
		3.	 
		4.	var theBiggest = function() {
		5.	  var result;
		6.	  a > b ? result = ["a", a] : result = ["b", b];
		7.	  console.log(result);
		8.	}
		9.	 
		10.	theBiggest(); 
	

Figure 37 - the findBiggestFraction() function re-written as an anonymous function

This gives us the output shown below.

Figure 38 - the output when executing the anonymous function shown in figure 37

What happens if we add this line to the script.


		console.log(theBiggest());
	 

So, we are console logging our variable, with its parentheses, and this gives us the output

Figure 39 image

Figure 39 - the output we see when we add an extra line to console log the variable

We can see in the output that the function has been called twice. In the line we added, the function is called from within the additional console.log() statement (which gives the second line of output). Since it doesn't return anything, the only thing to be returned to console.log() is the variable and since we haven't assigned a value to it, it shows as undefined.

If we add another line to the function so that it does return something, let's say


		return result;
	

our script now produces this output.

Figure 40 image

Figure 40 - the output from our script again, but this time with the function returning something

The output in figure 40 gives the impression that the function was called three times. However, it was still called twice. When it was called the second time in our console.log() statement, the return value was assigned to theBiggest. This just happens to be the same output (that is, we are console logging result) as we get from actually running the function.

To further illustrate this, let's change the return value to 1000 and change our calls to the function so that the script now looks like this.


		1.	var a = 5/7;
		2.	var b = 18/25;
		3.	 
		4.	var theBiggest = function() {
		5.	  var result;
		6.	  a > b ? result = ["a", a] : result = ["b", b];
		7.	  console.log(result);
		8.	  return 1000;
		9.	}
		10.	 
		11.	theBiggest();
		12.	console.log(theBiggest());
		13.	theBiggest();
		14.	console.log(theBiggest);
	

Figure 41 - the script amended so that we are playing around with the function calls and the return value

On line 11, we are calling the function and result is logged to the console from within the function.

On line 12, we are calling the function again from within a console.log() statement so again, we will see result logged to the console. The return value is then assigned to theBiggest and we output that to the console.

On line 13, we call the function again and I will explain the reason for doing that in a minute.

On line 14, we console.log theBiggest, and again, I will explain the reason for doing that in a minute. This causes the last line of our output to be logged to the console and all of the output is shown below.

Figure 42 image

Figure 42 - the output we see when executing the script in figure 41.

The first three lines of output are quite predictable. The reason I called the function again on line 13 is because I wasn't sure whether theBiggest would still reference the function after the return value (which we can see in the third line of the output in figure 42) had been assigned to it.

The fourth line of output shows that we can still call the function, so theBiggest does still reference it.

The strangest line of output is the last line which shows us that theBiggest references a function called theBiggest(). My expectation would have been that we would see the value of 1000 output here since we are referencing theBiggest without the parentheses. The output seems to show that this was a temporary assignment (if it was assigned at all) and theBiggest has effectively not changed.

In figure 39, we saw the output we got when we added the line


		console.log(theBiggest());
	

to the code shown in figure 37. I am now wondering what would happen if we revert our code so that it matches the code in figure 37 and then add this line


		console.log(theBiggest);
	

This will tell me whether the last line of output in figure 42 (which seemed to show that the biggest is no longer undefined) is because of the fact that we returned a value in the function or if it simply showed as undefined because we added the parentheses and this has confused the interpreter.

When we run this now, we get the output

Figure 43 image

Figure 43 - checking whether theBiggest is undefined if we console log it without parentheses

So this tells us two things. Firstly, when we saw the returned value in the output in figure 42, this was a side effect. That is, the value of 1000 was returned to console.log and so console.log logged it to the console.

It also shows us that theBiggest() is not undefined in our code, it is defined as a function, or at least, that is how the browser interprets it. This is largely academic, of course, and doesn't tell us anything about the usage of anonymous functions, but I think that it makes things a little bit clearer, even if it does leave some unanswered questions. For example, why did we see undefined in the output?

We can also pass arguments to an anonymous function and this works in more or less the same way as it does for named functions.


		1.	var x = 5/7;
		2.	var y = 18/25;
		3.	 
		4.	var theBiggest = function(a,b) {
		5.	  var result;
		6.	  a > b ? result = ["a", a] : result = ["b", b];
		7.	  return result;
		8.	}
		9.	 
		10.	console.log(theBiggest(x,y));
	

Figure 44 - our anonymous function re-written to work with arguments

It may also be worth noting that while we have used variables here, we could also pass actual values to the function (and this also applies with named functions) so we might add a line


		console.log(theBiggest(7/8,13/16));
	

This gives us the output

Figure 45 image

Figure 45 - the output when passing two sets of value (first a couple of variables and second two actual values) to the anonymous functions

I have to say that while I have seen that anonymous functions can be really useful (for example in Perl), I don't really see any great difference between a named function and ab anonymous function. I note that it was mentioned that we can assign an anonymous function to an event and this may be covered later in the course, but I don't know if a named function can be used to handle an event.

At this point, it just seems like a minor difference in syntax. Hopefully this will be covered later.

There is a JavaScript wiki book that has more information on anonymous functions here which also provides a couple of uses for anonymous functions, including as arguments to another function.

Immediately Invoked Functional Expressions

In the previous example, we were treating the variable as though it were a function and the course video notes, as we saw earlier, if you try to do something like


		console.log(theBiggest);
	

you will see that the function is being returned and this is what we see in the output. Actually, I didn't notice that the output was collapsed. If we expand this, it will look something like the output shown in figure 46.

Figure 46 image

Figure 46 - this is what the function looks like when we use the command, console.log(theBiggest)

Later on, we will see how we can make use of this property when hooking an anonymous function to an event.

We also saw that we were not able to return the result to theBiggest. If we wanted to use a return value, we had to create a new variable and assign the result of running the function to this new variable.

However, there is a way to do this, or something similar at least and this involves using an immediately invoked function expression. This looks a little like an anonymous function with two differences. Firstly, we put the whole function in parentheses. Secondly, we tag another pair of parentheses on the end of the function. Remember that the function is being invoked immediately and this second pair of parentheses is required for that.

If we are passing any arguments to the function, these would be placed inside the second set of parentheses. You could think of it like this. If you were calling a named function, lets's say it is called func(). If there are no arguments, you would call it like this.


		func();
	

If you need to pass any arguments to the function, lets say num1 and num2, you would do it like this.


		func(num1,num2);
	

Exactly the same is happening here, but rather than just the function name, you have the immediately invoked function expression. If we use the same function as the previous example, it will now look like this.


		1.	var theBiggest = (function(a,b) {
		2.	    var result;
		3.	    a>b ? result = ["a", a] : result = ["b", b];
		4.	    return result;
		5.	})(7/9,13/25) 
	

Figure 47 - our anonymous function, theBiggest(), re-written in the form of an immediately invoked function expression

As we can see, in this example, there are two arguments being passed to the function. If we add this line to the script


		console.log(theBiggest);  
	

the output we see is

Figure 48 image

Figure 48 - the output frim running theBiggest as an immediately invoked function

There are several implications here. The most important is that theBiggest is not being attached to the anonymous function. The function simply executes and assigns its value to theBiggest. That is, the return value determines what value theBiggest will take.

We also saw earlier that the position of our functions in the code is not important as far as the interpreter is concerned, although for humans, it is more normal to put the function before the function call. Sometimes, when you are passing variables to a function, this can mean that the variables are declared after the function is defined and that is fine.

In this case, however, the function is being invoked immediately, so its position in the code is important. Let's say we amend our script to create two variables which are passed to the function. We might end up with a script like the one shown in figure 49.


		1.	var theBiggest = (function(a,b) {
		2.	    var result;
		3.	    a>b ? result = ["a", a] : result = ["b", b];
		4.	    return result;
		5.	})()
		6.	 
		7.	var firstFraction = 7/9;
		8.	var secondFraction = 13/25;
		9.	 
		10.	console.log(theBiggest);
	

Figure 49 - adding a couple of variables so that we can pass them to the immediately invoked function - THIS WON'T WORK

The result of running this is shown in figure 50.

Figure 50 image

Figure 50 - the output we get from the code shown in figure 49

So, the result array was returned and it contains the values ["b", undefined]. The first element in the array was set to "b" because the ternary operator is set up in such a way that this always happens except when a > b returns true. If that happens, the value of the first element is set to "a". The value of the second element, which should be the value of b, is undefined. Actually, both a and b are undefined so a > b returns false, which is why we see "b" in the first element.

Looking back at our code, we can see that the arguments we passed to theBiggest are declared after the function has been called, so they are undefined when the call is made and therefore a and b are also undefined. If we rearrange the code like this


		1.	var firstFraction = 7/9;
		2.	var secondFraction = 13/25;
		3.	 
		4.	var theBiggest = (function(a,b) {
		5.	    var result;
		6.	    a>b ? result = ["a", a] : result = ["b", b];
		7.	    return result;
		8.	})(firstFraction, secondFraction)
		9.	 
		10.	console.log(theBiggest);
	

Figure 51 - the code in figure 49 rearranged so that we declare the variables before calling the function

If we run this code, we see that it runs correctly.

The main advantage of an immediately invoked function is that it is unaffected by the code that comes after it in the script and this can be useful. The can also be used to quickly populate a variable or a property in an object and are often hooked to event listeners for an immediate output.

ES2015: let and const

Until ECMAScript 2015 (or ES6), you either declared a variable with var so it is scoped according to where it is declared, or you omitted var making it a default variable. It is important to note that using var doesn't mean that your variable is not a global variable, that depends on where you declare it.

Now, we have two additional variable types and these are const and let. A const variable is simply a constant so that's quite straightforward. JavaScript, like most programming languages, follows the convention that the name of a constant should be all upper-case.

One point to note about constants in JavaScript. If you declare a variable and const and then try to change it, the script will stop so this is something that will break the script.

A let variable is a block scope variable, which sounds like it is just declared inside a block so that one may need a little more explanation! We will start by looking at var in a little more detail.

Consider the code shown here.


		1.	function logScope() {
		2.	  var localVar = 2;
		3.	 
		4.	  if (localVar) {
		5.	    var localVar = "I'm different!";
		6.	    console.log("nested localVar : ", localVar );
		7.	  }
		8.	 
		9.	  console.log("logScope localVar: ", localVar);
		10.	}
		11.	 
		12.	logScope();
	

Figure 52 - our logScope() function which demonstrates the scope of a variable declared with var

We start with a function in which declare a variable with var, localVar, so this is local to the function and we set its value to 2.

We then have an if statement with a condition that will always evaluate to true provided that localVar has a non-zero value. The if statement has a block of code and inside of this, we declare another variable called localVar and give it a value of "I'm different!", so this is local to the if statement's block of code.

Still inside the if statements code block, we then output the value of localVar to the console and exit the block.

We are still inside the function and we then output the value of localVar to the console and the function ends.

On line 12, we call the function.

Before I execute this, I want to speculate on what the output would be and the key point, here, is whether localVar is being treated as two separate variables with different scope. If that is the case, the first console.log statement on line 6 will output "I'm different!" and the second on line 9 will output the value 2.

Conversely, if JavaScript sees both of these variables as having the same scope, the result will be that we have declared the variable twice but it is the same variable. Since the last assignment of a value to localVar is on line 5 (where it is assigned the value, "I'm different!"), we would expect to see this value output twice.

Before I discovered that a let declaration gives you scope within a block, I would have expected the first result (two variables with different scope). However, I suspect that we will see the same value output twice and discover that we need to declare at least the variable inside the conditional code block with let so that it overrides the variable that has scope within the function.

Figure 53 image

Figure 53 - the output from the logScope() function

So, we see that there was only one variable! To fix this so that both variables are treated as differently, we obviously have to declare the variable inside the conditional code block with let. Let's try that and see what happens.

Figure 54 image

Figure 54 - the output we get from logScope() when the second localVar is declared with let

That suggests to me that the purpose of let is to allow you to declare a variable that overrides another variable with the same name that has greater scope.

Make Sense of Objects

JavaScript is object-oriented although not as completely object-oriented as, say, Java. You can, as we have already seen, write entire scripts without using anything that looks like object-oriented code. In fact, it might be better to say that JavaScript allows you to use and create objects.

As you might expect, the main reason for doing this is that it can make complex data structures much more manageable. As an example, let's say that we want to create a script that uses data relating to a course such as JavaScript Essential Training.

We might create variables to hold the following:

and so on. This could get quite messy, especially if this is mixed in with other code. So this is a good candidate for an object where we can create properties for all of the above and anything else we need to record about a course, and we can create custom methods for manipulating these attributes and providing any other required behaviour.

The big advantage is that if we need to create a second course object, we don't have to worry about creating appropriate variables for it, we just need to create a new instance of course (pun not intended)!

The method for creating a class in JavaScript is a little weird compared to other languages. For instance, let's say that we want to create a class for our course objects. The short answer for "how do you do that in JavaScript?" seems to be that you don't. You just go ahead and create an object and then set its properties.

To start with, we create a new object in a way that suggests we are invoking a constructor.


		var course = new Object;
	

We can then create properties for the object with statements such as


		course.title = "JavaScript Essential Training";
	

and so on. There is also a shorthand version of this which allows us to attach several properties to one object and this would look like


		1.	var course = {
		2.		title: "JavaScript Essential Training",
		3.		instructor: "Morten Rand-Hendriksen",
		4.		level = 1;
		5.		published = true;
		6.		views = 0;
		7.	} 
	

We can access an object as an entity by referencing it directly, as in


		console.log(course); 
	

We can also reference a property using the object name and dot notation to append the property like this.


		console.log(course.title); 
	

In figure 55, our script creates a course object, adds some properties with values and then logs the course object and then a couple of the course properties to the console.


		1.	var course = new Object();
		2.	 
		3.	var course = {
		4.	  title: "JavaScript Essential Training",
		5.	  instructor: "Morten Rand-Hendriksen",
		6.	  level: 1,
		7.	  published: true,
		8.	  views = 0,
		9.	}
		10.	 
		11.	console.log(course);
		12.	 
		13.	console.log(course.title);
		14.	console.log(course.instructor); 
	

Figure 55 - code to create an object called course, add some properties and then console log the object as an entity followed by some of the individual properties

The output we get from this is

Figure 56 image

Figure 56 - the output we get from running the script in figure 55

If we want to add a function, we can do that by adding an anonymous function. We add this as though we were adding another property, so our script would now look like this.


		1.	var course = new Object();
		2.	 
		3.	var course = {
		4.	  title: "JavaScript Essential Training",
		5.	  instructor: "Morten Rand-Hendriksen",
		6.	  level: 1,
		7.	  published: true,
		8.	  views = 0,
		9.	  updateViews: function() {
		10.	    return ++course.views;
		11.	  }
		12.	}
		13.	 
		14.	console.log(course);
		15.	 
		16.	console.log(course.title);
		17.	console.log(course.instructor); 
	

Figure 57 - adding a method to our object

Object Constructors

In the previous example, we created a course object and this was an instance of the Object class. If we want to create a class of type Course, we have to create an appropriate constructor.

This is created as a function where the name of the function matches what is effectively the class name. It takes a number of arguments which are used to set the values of the object's properties.

Inside the constructor, we use this to as a self-reference, so we would, for example, set the course title with


		this.title=title;
	

We do something similar for all the other properties. We can also provide it with a method in the same way so if we want to use the same updateViews method from the previous example, we would set this up as


		1.	this.updateViews = function() {
		2.		return ++this.views;
		3.	} 
	

This gives us a complete constructor as shown below.


		1.	function Course(title,instructor,level,published,views) {
		2.	  this.title=title;
		3.	  this.instructor=instructor;
		4.	  this.level=level;
		5.	  this.published=published;
		6.	  this.views=views;
		7.	  this.updateViews=function() {
		8.	    return ++this.views;
		9.	  };
		10.	}
	

Figure 58 - the Course() constructor

Note that, as is common with object-oriented languages, the name of the course is the same as the 'class' (I use the term loosely here) and begins with an upper-case letter.

With the constructor, we can now create our object again, but this time using the constructor like this.


		var course01 = new Course("JavaScript Essential Training", "Morten Rand-Hendriksen", 1, true, 0);
	

We can also log this to the console, just as we did before, with


		console.log(course01); 
	

This gives us the exactly the same output as we saw in figure 56, except that we didn't also log individual properties. We could do that, if required, in the same way.


		console.log(course01.title); 
	

One advantage with this approach is that we can very easily create further course objects with the appropriate arguments.


		var course02 = new Course("Up and Running eith ECMAScript 6", "Eve Porcello", 1, true, 123456); 
	

We can also do something slightly more advanced such as create an array of course objects like this.


		1.	var courses = [
		2.	  new Course("JavaScript Essential Training", "Morten Rand-Hendriksen", 1, true, 0);
		3.	  new Course("Up and Running with ECMAScript 6", "Eve Porcello", 1, true, 123456);
		4.	];
	

This allows us to console log all of the courses with a single console.log statement.


		console.log(courses); 
	

We can also access the property of any of the objects in the array using its index value and the property name. For instance, if we want to log the instructors name for course02, we would do that with


		console.log(courses[1].instructor); 
	

We can, in a similar way, call the objects updateViews() method.


		console.log(courses[1].updateViews()); 
	

This increments the value of courses[1].views and outputs the result to the console. The console.log part is not required here.


		courses[1].updateViews; 
	

would also increment the value of courses[1].views, it just wouldn't output the result to the console.

For reference, the script in its current state is shown below.


		1.	function Course(title,instructor,level,published,views) {
		2.	  this.title=title;
		3.	  this.instructor=instructor;
		4.	  this.level=level;
		5.	  this.published=published;
		6.	  this.views=views;
		7.	  this.updateViews=function() {
		8.	    return ++this.views;
		9.	  };
		10.	}
		11.	 
		12.	var courses = [
		13.	  new Course("JavaScript Essential Training", "Morten Rand-Hendriksen", 1, true, 0),
		14.	  new Course("Up and Running with ECMAScript 6", "Eve Porcello", 1, true, 123456)
		15.	];
		16.	 
		17.	console.log(courses);
		18.	console.log(courses[1].instructor); 
	

Figure 59 - the constructor for course and some additional commands to create an array of courses and produce some output

The output from running this is

Figure 60 image

Figure 60 - the output produced by the code in figure 59

Sidebar: Dot Notation and Bracket Notation

We saw that it is possible to access properties of an object using the sort of dot notation that is normal in object-oriented programming. JavaScript provides a separate form of syntax to do the same thing and that is called bracket notation.

Let’s take an example of the dot notation used in the code shown in figure 59.


		console.log(courses[1].instructor); 
	

Here, inside the brackets, we have the objects name or reference followed by a dot and then the property name. If we convert this to square bracket notation, we remove the dot and put the property name in a string in square brackets like this


		console.log(courses[1]["instructor"]; 
	

These are just alternative forms of syntax and in most cases, you can use either and you can, if you need to, use both forms of syntax in the same script.

The reason we need this second form of the syntax is that sometimes, we may be working with objects that come from outside of our script and where the property names don't work with dot notation. As an example, let's say this applied to course and it has a property called WP:image. Using dot notation, we would access the property with something like


		course.WP:image;
	

This confuses JavaScript because : would be seen as an operator, and it will give you an error. You can resolve this using bracket notation. Using this notation, the property name is inside a string so JavaScript won't try to parse it and it won't give an error. The syntax, in this case, would be


		course["WP:image"];
	

To sum up, the two forms of notation are generally interchangeable, so you can use either. If the property name is such that it gives you problems when you try to access it with dot notation, you then have to use bracket notation.

Closures

A closure, is a little bit of a weird and probably misleading name. Possibly enclosure would be a better name! Essentially, any function is an enclosure and I will explain this by reference to an example.


		1.	function doSomeMath() {
		2.		var a = 5;
		3.		var b = 4;
		4.		var sum = a + b;
		5.	 
		6.		return sum;
		7.	}
		8.	 
		9.	var theResult = doSomeMath();
		10.	 
		11.	console.log("The result: ", theResult);
	

Figure 61 - the doSomeMath() function

The doSomeMath() function creates three variables, a, b and sum and these are local to the function. That is, we cannot access these variables outside of the function, that would give us a scope error (unless they were global variables).

After the function is defined, it is called, it performs its arithmetic function and returns the result, which is 9, to the function call. The return value is assigned to the variable, theResult. This is exactly how we expect a function to work and it's how a function works, perhaps, in any programming language.

But the function does something that might seem a little weird. We can't see that in this version of doSomeMath(), so we will change it by replacing the variable sum and its expression with a function called mulriply that multiplies a and b and then returns the result. Since this function is created inside of the doSomeMath() function, that's where it returns the value to.

Next, instead of returning this result to the call to doSomeMath(), it returns the function. The amended code now looks like this.


		1.	function doSomeMath() {
		2.		var a = 5;
		3.		var b = 4;
		4.		function multiply() {
		5.			var result = a * b;
		6.			return result;
		7.		}
		8.	 
		9.		return multiply;
		10.	 
		11.	}
		12.	 
		13.	var theResult = doSomeMath();
		14.	 
		15.	console.log("The result: ", theResult());
	

Figure 62 - the doSomeMath() function modified to return a function rather than a value

When we run this, we get the result 20 which may surprise you. The fact that 4 multiplied by 5 shouldn’t come as too much of a surprise! But if you look at line 13, we are creating a variable and assigning the multiply function to it. On line 15, we are invoking that function by referencing the variable and we are getting the correct result.

This is in spite of the fact that two of the variables were created outside of the multiply function! They were created inside the doSomeMath() function.

In one context, that is where the multiply function is created inside the doSomeMath() function, it is clear that multiply can access these variables. In another context, that is where the multiply function is called from outside of the doSomeMath(), it is less clear since it may be reasonably expected that the multiply function can only access variables that are local to itself or the function from which it is being called.

The reason this works is because when the multiply function is created, it is essentially linked to the variables that it needs in order to function. Normally, when a function is closed, any variables that are local to that function cease to exist so the memory they use, for instance, is freed.

In this case, since we are returning a function that will still need to access these variables, they are kept in memory and this combination of the function and the variables associated with it is called a closure.

It is worth noting that any function you create is bound to the variables it creates, so technically speaking, every function is a form of closure, but we normally only think of it as such when we make use of it in this way to call a function with variables that are not directly local to it.