<h2class="sectiontitle">Objects: A Practical Introduction</h2>
<p>JavaScript is a prototype based object oriented programming language which essentially means that each object in JavaScript is an instance of some prototype. The prototype describes the properties an object must have to be whatever we are saying the object is. For example, we previously saw a backpack object and this has what we might call the backpack properties.</p>
<preclass="inset">
• name - this isn't really a backpack property, an object can still be a backpack without a name, but it is useful to give it one to make it more easily identifiable.
• volume - a backpack must be able to carry things so this tells us something about how much it can carry, from which we can infer the fact that it can carry things.
• number of pockets - again, this is a property of a backpack although not essential, a backpack doesn't have to have pockets - in that case the number of pockets is
zero but this is a typical property associated with a backpack, so it seems perfectly reasonable to use it as a descriptive feature of a backpack.
• two straps - this is an essential feature of a backpack although we are specifying the length of each strap so the fact that there are two straps is implied.</pre>
<p>Objects typically have methods allowing us to change the state of an object. For example, with a backpack, we can change the length of the straps, change the status of the 'lid' from closed to open or closed to open. In addition, there will normally be some methods to allow us to check the current state of an object (at least normal in object-oriented programming, I'm not sure if this is normal when working with objects in JavaScript.</p>
<p>An object in JavaScript is a variable quite different from other types of variable such as a string or an integer, but in some ways they are exactly the same as other types of variable. For example, in our backpack object, we use a string to hold a value for name and we use integers to hold values for the volume, number of pockets and strap length. But we can also use another object for a value of one of the backpack's properties. There are no obvious examples, but let's say that we wanted to create an array to hold the contents of a backpack. The values in that array may also be objects - that's not to say that if we want to use an object for some property of the backpack, it has to be inside a collection like an array. The point is that an object can have properties that are themselves objects.</p>
<h2class="sectiontitle">JavaScript Objects: The Code Version</h2>
<p>Creating an object in JavaScript is different from most programming languages where an object is an instance of a class. In JavaScript, an object is declared as a constant followed by a pair of curly braces that contain the object's properties. For the backpack, that means our starting point is</p>
<preclass="inset">
const backpack = {}</pre>
<p>Properties are added by using the property name followed by a colon and then the property value. For example, to set the name, we use</p>
<preclass="inset">
name: "Everyday Backpack",</pre>
<p>As we mentioned earlier, the value of a property can be another object. For example, strapLength is an object with two properties, left and right so we declare this as</p>
<preclass="inset">
strapLength: {
left: 26,
right: 26,
}</pre>
<p>Note that we use a comma at the end of the property declaration.</p>
<p>A property can also have a function as a value. For example</p>
<preclass="inset">
toggleLid: function (lidStatus) {
this.lidOpen = lidStatus;
},</pre>
<p>Notice that the statements inside the function are terminated with a semi-colon and since the function is a property of the backpack object, the whole declaration is terminated with a comma.</p>
<p>To call a function from outside the object, you use it's name and provide any required arguments which in this case is lidStatus and the function uses that to set the value of the lidOpen property.</p>
<p>You may have noticed that like other object-oriented programming languages, JavaScript uses the keyword <em>this</em> to refer to the current object.</p>
<h2class="sectiontitle">Object Containers</h2>
<p>The container for an object is the variable, in the previous example, this was backpack. We declare it as a constant so that it's value cannot be over-written - essentially, we can't replace the object with another value.</p>
<p>For example, we have the backpack object in a JavaScript page in exercise 03_03. If we remove the const keyword, we could then change the value of backpack in the console to, let's say, 5 like this.</p>
<preclass="inset">backpack = 5</pre>
<p>Now backpack is simply an integer variable holding the value 5. If the const keyword is used and we try the same thing in the console, we will get an error.</p>
<preclass="inset">
Uncaught TypeError: invalid assignment to const 'backpack'
debugger eval code:1</pre>
<p>In spite of the fact that the object is declared as a constant, this only means that backpack must always reference that object, but we can still modify the object's properties. We saw that with the the toggleLid function which can modify the value of the lidOpen status. We can also use dot notation to access and modify an object's properties. For example, we we wanted to change the value for the number of pockets (pocketNum), we can do that with</p>
<preclass="inset">backpack.pocketNum = 20;</pre>
<p>So, when we declare the object as a constant, we can modify its properties, but we can't accidentally destroy the object by, say, assigning an integer to backpack.</p>
<h2class="sectiontitle">Object Properties</h2>
<p>As we have seen, properties are name value pairs separated by a colon. The name can be any string and according to the JS standard, should only contain letters, numbers, the dollar sign or an underscore character. If you add any other character to the name such as a hyphen, the JavaScript will crash because of the incorrect code.</p>
<p>The property value can be anything you can assign to a variable so it could be a string, a number, a character or another object and it could also be a function in JavaScript.</p>
<p>We have already seen in the console , that we can access an object with its name. When we type backpack in the console, the console returns the entire object and we can examine the properties, including the functions. This works the same way inside JavaScript. If you want to access the whole object, you just need to use its name. Let's say, for instance, we want to output the whole object to the console for debugging purposes, we can do that from within the JavaScript with the command</p>
<preclass="inset">console.log(backpack);</pre>
<p>We can also add a bit of text to the output sent to the console.</p>
<p>We can summarise all of this by saying that the objects name, backpack, can be used to access the object as a whole entity, including its properties and functions.</p>
<p>As we saw earlier, we can use dot notation with the object name in order to access an individual property. If we wanted to output that property to the console, for example, we can do that with</p>
<preclass="inset">console.log("The pocketNum values is: ", backpack.pocketNum);</pre>
<p>Remember that one of the properties of the backpack object is, itself an object and that is straplength. We could access the object like this.</p>
<preclass="inset">console.log("The strapLength object is: ", backpack.strapLength);</pre>
<p>If we wanted to access an individual property, we can do that with dot notation as well. For example, let's say we want to pass the value for left to the console, left is a property of strapLength and strapLength is a property of backpack, which gives us</p>
<preclass="inset">console.log("Strap Length L is: ", backpack.strapLength.left);</pre>
<p>Dot notation is easy to use and easy to read. In the last example, it is easy to see that we are accessing the left property, that it is a property of strapLength and that strapLength is a property of backpack. Because it is easy to use, dot notation is the preferred method for accessing an object's, but not the only one. We can also use bracket notation and this can be better when you need more control, perhaps because you need to use a variable as the property name (for instance, you might have a variable outside the object called strapLen that represents either the left or right strap and you want this to access the appropriate property inside the backpack object. Dot notation won't work here, but you can use bracket notation.</p>
<preclass="inset">console.log("Strap Length L is: ", backpack.strapLength[strapLen]);</pre>
<p>Another example might be where you have a function that returns a value which you assign to a variable called, for instance, query. Let's say that query has a value of .pocketNum and you want to use the variable to access the corresponding backpack property, again, you can use the bracket notation.</p>
<preclass="inset">console.log("The pocketNum values is: ", backpack[query]);</pre>
<p>Another situation where bracket notation is useful is where you have a non-standard property name. As we mentioned earlier, property names must only include letters, numbers, the dollar symbol and the underscore character. In addition, a property name can't start with a number. Now, JavaScript doesn't actually enforce these rules, so if you create a property name that breaks them, you won't be able to access the property with dot notation so you have to use bracket notation.</p>
<p>I tried to experiment with the property names of backpack and the result was an error when I tried to do that. However, JavaScript sometimes works with JavaScript objects from somewhere else and objects generated in this way don't always conform to the JS standards, in which case, you may need bracket notation to access their properties.</p>
<p>To sum up, you should use dot notation to access the properties of objects created within your own JS code or that conform to the JS standards, but where this is not possible because a property has a non-standard name or where you want to access a property using a variable, you should use bracket notation.</p>
<h2class="sectiontitle">Practice: Build a New Object</h2>
<p>For this practice exercise, which is in the practice folder under 03_07, we just want to take some every day objects and create their equivalents in JavaScript and then use the console to access the objects and their properties. The code for this exercise is nothing more than a more or less empty HTML document and an empty JavaScript file. Objects can be created in the JavaScript file and we can then use the HTML file (which does have a link to that JS file) to open up the page with the Live Server. The page will be blank but will have access to the JavaScript so then we can use the console to access the objects we add to the JS. The objects should include at least one that has other objects as properties.</p>
<p>I have created two objects. The first is microphone and it has four data properties and one function. The function is called record and it takes a string as input and sets the data property, text, to the value passed to the function.</p>
<p>To test it, I have output three of the data properties to the console, executed the function with a string of "Jo reggelt!" and then output the value of text to the console.</p>
<p>The second object is called cd and it has four properties and no functions. Three of the properties have a string or integer value and the fourth is an object containing a track listing. It has 15 properties, all of which are objects representing the 15 tracks of the cd. Each of the 15 objects has two properties, a title and the writers of the track.</p>
<p>To test it, I have output the first three properties to the console. I have then output the tracks object as a single object. I have then output four of the tracks to the console, first as an object and then I have output the title and writers for each of those four tracks.</p>
<p>The JavaScript for this exercise is shown in <ahref="codesamples/chapter3/sample1.html"target="_blank">code sample 1</a> (opens in a new tab).</p>
<h2class="sectiontitle">Object Methods</h2>
<p>Since a function can be a property of an object, you will usually see them being declared like any other property (in some ways). Let's take the following as an example and break it down.</p>
<preclass="inset">
record: function (speech) {
this.text = speech;
},</pre>
<p>First, we have the property name, in this case, record. This is followed by a colon. If you compare this to another property, say</p>
<preclass="inset">brand: "Blue",</pre>
<p>you can see that after the colon, we have the value and that applies here as well, but the value is a function. Bear in mind that a function doesn't have to an object property, so after the colon, we have exactly what you would have if you declared a function outside of an object, although it does look like an anonymous function. So, we have the keyword function, we are missing the function name and then we have a set of parentheses which contains the function parameters (they will be empty if there are none). We then have the function body wrapped up in curly braces. Since we have assigned this function to a property of the object, that property is the function's name so in this case, the function name is record.</p>
<p>As we saw in the previous exercise, you can call the function using dot notation. That is the object name followed by a dot and then the function name with any arguments that may be required.</p>
<p>There is also a shorthand for creating a function in an object where we remove the function expression so we just have the function name followed by the parameters and the code body so if we write our function with this shorthand, we get</p>
<pre>
record (speech) {
this.text = speech;
},</pre>
<p>This works in exactly the same way. Although both ways of creating a function property work, the shorthand version is less common since by using the function expression, we are making it a little clearer that we are defining a function as the property so its a bit easier to read.</p>
<p>It is very important to remember that when we run functions to change the state of an object, this is happening inside the browser. In other words, if a function runs after being triggered by a browser event such as clicking a button or is run in the browser, this does not change the original code so if you then refresh the browser, everything will revert to the same stage it was in when the page was originally loaded. </p>
<h2class="sectiontitle">Practice: Build a New Method</h2>
<p>For this exercise (the code is in the 03_09 directory in the practice folder), we are starting out with the code to create a backpack object. It has functions to set the status of toggle lid or to change the length of the straps. Note that the function to change strap length changes both at the same time, so even if you only want to change one of the lengths, you still have to pass the lengths of both to the function.</p>
<p>The goal of this exercise is to create functions that will allow us to set each property and then to use these to change the state of the object which we will then output. For comparison, I will also output the state of the object before any changes are made as well. Since we have a function that changes the lengths of both straps, I will create two functions to change the length of each strap individually. Apart from strapLength, the properties I will create a function for are name, volume, color and pocketNum. I am curious to know whether it is possible to modify the value of a function in the same way to effectively assign a different function to it so I will try to write a function that changes the toggleLid function so that it outputs some statement to the console rather than updating the toggleLid function.</p>
<p>The functions I created are as follows.</p>
<preclass="inset">
set_name: function (new_name) {
this.name = new_name;
},
set_volume: function (newVolume) {
this.volume = newVolume;
},
set_color: function (newColor) {
this.color = newColor;
},
set_numPockets: function (newPockets) {
this.pocketNum = newPockets;
},
set_left_strap: function (newLength) {
this.strapLength.left = newLength;
},
set_right_strap: function (newLength) {
this.strapLength.right = newLength;
},
set_toggleLid: function (newFunction) {
this.toggleLid = newFunction;
},</pre>
<p>The output this gives us for the initial state of the backpack is</p>
<preclass="inset">
{
"name": "New backpack",
"volume": 45,
"color": "Red",
"pocketNum": 22,
"strapLength": {
"left": 36,
"right": 38
}
}</pre>
<p>The output after the various functions have been called to amend the backpack's properties is</p>
<preclass="inset">
{
"name": "New backpack",
"volume": 45,
"color": "Red",
"pocketNum": 22,
"strapLength": {
"left": 36,
"right": 38
}
}</pre>
<preclass="inset">
Checking if the new function works
I have hijacked the toggle lid function!</pre>
<p>This final piece of output does show that I was able to overwrite the function for toggleLid with a new function that does something else. I wrote this function in such a way that it accepts a function as an argument and sets the value of toggleLid to this new function. The function is as follows:</p>
<preclass="inset">
set_toggleLid: function (newFunction) {
this.toggleLid = newFunction;
},</pre>
<p>You might notice that there isn't anything particularly different about this code and although we have used newFunction as the parameter name, there is nothing here in particular that causes the toggleLid function to be replaced with a different function. It simply sets the value of toggleLid to whatever parameter is passed to the set_toggleLid function and this can be a function or it can be a different type of value such as a number. When we call the function, if we pass it a function as a parameter, it will become that function. In that sense, I guess you could pass a function as a parameter to any property which then becomes a function.</p>
<p>In this case, all that we needed to do in terms of defining the function was to set it up in such a way that the value of toggleLid is changed to the parameter we pass to the set_toggleLid function. This means that if we want to set this to a new function, we have to pass the new function to the set_toggleLid function.</p>
<preclass="inset">
backpack.set_toggleLid(function () {
console.log("I have hijacked the toggle lid function!");
});</pre>
<p>To do this, inside the brackets, we just need to have the word function followed by parameters and the list of arguments the new function takes (none, in this case) and a pair of curly braces containing the code we want to be executed by the new function.</p>
<p>It may be worth noting that, in common with a few other programming languages, JavaScript uses duck typing to determine the type of a variable. Unlike, for instance, C or Java, we don't need to specify what type of argument will be passed to a function. When we call the function, JavaScript will infer the variable type based on the argument provided. So, in this example, we are passing a function to the set_toggleLid function and so JavaScript treats it as such and creates this new function called toggleLid. If we pass the same function a different type of variable, let's say the number 5, JS will set the value of toggleLid to the number 5.</p>
<p>This type of syntax is generally a little easier top work with than similar syntax in a strongly typed language like C, but there can be a downside to that in that sending the wrong type of value may work but give unexpected results.</p>
<p>We created a backpack object simply by creating a constant to hold it and then add properties, including functions. If we need to create multiple objects of the same type, we can create a variable with all of the properties so, for example, we could create more backpack objects. The downside of this approach is that if we want to make a change to the backpack objects, we have to change each object individually. However, as in other programming languages, we can use classes to create object templates so any changes we make to the class are going to be applied to any object created from the class.</p>
<p>To demonstrate how this works, there are three file for exercise 03_10.</p>
<preclass="inset">
• Backpack.js - this is the file that includes our class, by convention, the class name starts with an upper case letter.
• script.js - in this file, we create a backpack object.
• index.html - this file imports both the JavaScript files and allows us to access the objects and the class via the console.</pre>
<p>The JavaScript code for this chapter is in <ahref="codesamples/chapter3/sample2.html"target="_blank">code sample 2</a> (opens in a new tab).</p>
<p>In Backpack.js, we have the class followed by the class name (as I mentioned, this normally starts with an upper case letter). We then have the object constructor followed by the object properties and then the object functions.</p>
<p>The major difference between creating objects using a class and creating objects by simply declaring them as we did previously is the use of the constructor which accepts a number of parameters corresponding to each of the properties so we can completely set up an object with all its properties initialised with the parameters passed to the constructor.</p>
<p>This file is imported into the script.js file. We can then create an object like this</p>
<preclass="inset">
const everydayPack = new Backpack(
"Everyday Backpack",
30,
"grey",
15,
26,
26,
false
);</pre>
<p>We can, of course, create as many of these backpack objects as are required using the constructor. Notice, as well, that when we invoke the constructor, the variable declaration is similar to the one we saw in previous examples but we have added the new keyword indicating that this is a new instance of class Backpack.</p>
<p>This method for creating a class where we use the keyword class followed by the class name is referred to as a class declaration. In JavaScript, we can also use a class expression which is similar but creates a constant with the class name and assigns the class (including all of its properties to that constant. In the exercise, we used the class declaration like this.</p>
<preclass="inset">class Backpack { ... }</pre>
<p>If we had use a class expression, the first line of our class would look like this.</p>
<preclass="inset">const Backpack = class { ... }</pre>
<p>The trend seems to be to use an expression over a declaration but they are exactly the same thing so this is just a matter of preference. Personally, I don't think that the expression really adds anything so I would tend to use the declaration, but this may simply be due to the fact that the declaration is more familiar to me since I have some experience with object oriented languages.</p>
<p>In the HTML file, we have imported both of these JavaScript files as modules and you may recall, one of the reasons for doing this is that it tells the browser that these files may depend on each other. Note that classes are only ever accessed by other JavaScript files, we don't access them from the browser so it is a good idea to declare these files and any other JS files that use them as modules.</p>
<p>Now that we have looked at the code used top define an object, let's look at the script.js file which is where we instantiate the object. The code is in <ahref="codesamples/chapter3/sample2.html"target="_blank">code sample 2</a> (opens in a new tab).</p>
<p>Here, we are importing the Backpack class from Backpack.js and then creating an instance (everydayPack) using the class constructor, so we are passing a series of arguments to the constructor and these will initialise the object's various properties. The result is that we then have a backpack object with all the correct properties.</p>
<p>We can now access the object either as an entity or, using dot notation, we can access a specific property and you can see this in the last two lines of script.js where we are using console.log to output the object and then a single property of the object (the value of pocketNum). We can examine the object in the browser developer tools and we can get some useful information about it, not just the value of the properties, we can also see that it was created from a class using a constructor and we can see the arguments that were passed to that constructor.</p>
<p>It is important to remember that you cannot create objects from a class until that class has been defined so it is generally best to define it in a separate file and then import that file into the file where you want to create objects. All imports need to happen at the top of the file where it is being used, so that pretty much guarantees that the class will be available when needed.</p>
<p>If you make any changes to a class, for instance by adding a property, that change will be applied automatically to any objects created from that class.</p>
<h2class="sectiontitle">Object Constructors</h2>
<p>The method for creating classes described above is the standard way of doing that, but there is an older, less advanced method which was used before this functionality was available and it essentially uses a constructor function to create objects. This is different to the previous methodology where the class definition included a constructor function as one of its methods. In this case, the constructor function is the entire class and it therefore includes any methods the class needs (these were separate in the previous example).</p>
<p>The code for the object constructor function is shown in <ahref="codesamples/chapter3/sample3.html"target="_blank">code sample 3</a> (opens in a new tab). The syntax is quite similar to that of the first method we saw for creating a new object using a simple declaration as shown in <ahref="codesamples/chapter3/sample4.html"target="_blank">code sample 4</a> (opens in a new tab). The main difference is that the object constructor function declares properties without giving them any values. The values are provided as parameters when the constructor function is invoked and this is similar to the way in which the constructor is used when we have defined a class as an object template. The difference between the object constructor function and a class function is that in a class definition, the constructor is just a method and it is separate from the other functions and the properties. In the object constructor function, all of the classes functions are contained within the constructor.</p>
<p>The code in <ahref="codesamples/chapter3/sample3.html"target="_blank">code sample 3</a> (opens in a new tab) also includes the code to call the object constructor function to create an object. Here, we are simply calling the constructor with the appropriate arguments as we did previously.</p>
<p>The object constructor function provides exactly the same result that we would get by using a fully defined class, but is not really used anymore since classes provide more functionality than the object constructor function, but you may see the latter method used in old code. Although it is unlikely, there may be a scenario where you have to use an object constructor function in order to create objects, for instance if the platform you are working on doesn't support classes.</p>
<h2class="sectiontitle">Practice: Build a New Object with a Constructor</h2>
<p>For this exercise, I will create a couple of classes for the cd and microphone objects I created for an earlier exercise and write a few lines of code to test these.</p>
<p>The microphone class is relatively straightforward and the code can be found in <ahref="codesamples/chapter3/sample5.html"target="_blank">code sample 5</a> (opens in a new tab). In the script file, I have added code to create a Microphone object, output that Microphone object to the console, invoke the record message to simulate the recording of an audio message which is stored as text and then accessed this text property to display that message in the console.</p>
<preclass="inset">
const myMic = new Microphone("blue", "silver", "£92.65");
console.log("My microphone is ", myMic);
// record some audio with the mic
myMic.record("Good Morning Vietnam!");
console.log(myMic.text);</pre>
<p>The second class I created was CD which records the data for a cd that you might store in a music database. This also has four properties and one method. The thing that makes this a little bit complicated is the property, tracks, is intended to store the list of tracks and when I created this object in an earlier example, I wanted to create this list of tracks as an array.</p>
<p>I then tried to write an addTrack method that accepted a number, a title and a writer as arguments and used the number as the array index and inserted an array with both the writer and title as elements but that didn't work. I then tried a similar approach where a new object was created with a writer and title and tried to use the number as an index to insert that object into the array and this also didn't work.</p>
<p>This is the method shown in sample6.html and I wasn't able to fix it, but as I mentioned earlier, arrays will be covered later in the course so I don't want to get too hung up about this. Hopefully, at some point I will learn enough about how arrays work in JavaScript to be able to fix it.</p>
<p>The code I used to test the CD class was</p>
<preclass="codesample">
const oneStepBeyond = new CD("One Step Beyond", "Madness", 1979);
<p>Notice that the error is in the script.js file which shows that the syntax in the CD.js file is correct. I don't believe that the error is in the script.js file (not a syntax error at least, so the likeliest explanation is a semantic error in CD.js. That is, the code isn't doing what I was expecting it to do. Since it mentions that this.tracks is undefined, that means that there are two possible sources for an error. Either the browser doesn't recognise what <em>this</em> is or it doesn't recognise the tracks function</p>
<p>I will briefly describe what I though would happen. In script.js, we have created an object of class CD called oneStepBeyond. When the addTrack method is called, it is called on that object so <em>this</em> should represent the cd object. I am using it's method with the correct parameters and you will notice in the output shown above that the first track was actually added to the array.</p>
<h2class="sectiontitle">Global Objects</h2>
<p>JavaScript also includes some built-in classes that work just like the classes we have already seen. More information on these can be found in the <ahref="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects">MDN Web Docs</a>.</p>
<p>An example of this is the Date class and to demonstrate this, we will add a property to the Backpack class called dateAcquired which will allow us to later calculate how old the backpack object is. One way to do this would be to create a new Date object like this, assuming that the Backpack class has already been modified to have a property called dateAcquired which is set as part of the constructor.</p>
<preclass="inset">var date = new Date();</pre>
<p>We can then pass our date object to the constructor function when creating the backpack object so that it sets the dateAcquired property to the value of the new date object.</p>
<preclass="inset">
const everydayPack = new Backpack(
"Everyday Backpack",
30,
"grey",
15,
26,
26,
false,
date
);</pre>
<p>It might be worth pointing out here that Morten seems to favour this style of code where each parameter of the constructor is on a separate line. The more familiar style, for me at least, puts these on a single line like this.</p>
<p>For me, this makes it clearer that we have a single call to the constructor with, in this case, 8 parameters so you may see this style in code that I write myself.</p>
<p>In any case, we have created a date object which essentially acts as a time stamp storing the date and time when it was created and we have used this to set the date and time at which the backpack object was created.</p>
<p>Of course, these are two separate commands and in fact, the date and time recorded is the date and time when the date object was created rather than when the backpack object was created but since these happen in consecutive lines of code, there will be no appreciable difference unless there is some problem that causes execution to be paused but this is highly unlikely. A better option might be to create the object as part of the function call like this</p>
<preclass="inset">const everydayPack = new Backpack("Everyday Backpack", 30, "grey", 15, 26, 26, false, var date = new Date());</pre>
<p>but JavaScript doesn't seem to allow this. An alternative would be to have the constructor create its own Date object like this</p>
<preclass="inset">this.dateAcquired = new Date();</pre>
<p>This seems to work perfectly well. Note that this has been a slight digression - none of this is covered in the course video, at least not at this point where the Backpack object is created with a date value so it's not really using the Date class at all in this code. Presumably Mortem created a date object and then copied the value and is passing it to the constructor as a string. I guess that in reality, if you only wanted to record the date, you would probably just use the date as a string (by this, I mean today for example, you might just input the address as 28 Sept), but we might provide an explanation for why this is not the case in a second.</p>
<p>The Backpack class also has a new method for calculating the age of a backpack as follows.</p>
<preclass="inset">
backpackAge() {
let now = new Date();
let acquired = new Date(this.dateAcquired);
let elapsed = now - acquired; // elapsed time in milliseconds
let daysSinceAcquired = Math.floor(elapsed / (1000 * 3600 * 24));
return daysSinceAcquired;
}</pre>
<p>This method, when it is called, creates a new Date object called now with the current date and time. It then creates a second Date object called acquired and sets its value to the time and date of dateAcquired (that is, it copies the backpacks dateAcquired property) and this probably explains why the string used to initialise dateAcquire since it allows us to create the object, but give it the date/time that we want. We can then subtract acquired from now and this gives us the elapsed time in milliseconds</p>
<p>Since I had amended the code so that dateAcquired is created as an instance of Date, I didn't need to do that conversion so that gives me a slightly different version of this function.</p>
let elapsed = now - acquired; // elapsed time in milliseconds
let daysSinceAcquired = Math.floor(elapsed / (1000 * 3600 * 24));
return daysSinceAcquired;
}</pre>
<p>In this version, I just need to grab the value of dateAcquired and assign it to acquired, but I could actually omit this line altogether and simply use dateAcquired in the subtraction.</p>
<p>An interesting question that this raises is whether it is better to initialise dateAcquired as a string and convert it to a Date object when calling the backpageAge function or just create it as a Date object in the first place as I did. I tend to like my method better, but it does have one very big disadvantage and that is that the value is updated whenever the code runs and that includes when the page is refreshed. Given the fact that it is intended to record the date/time when the object is created, this is probably why Morten chose the approach that he did and he was probably right to do that. On the other hand, it does mean that the value has to be hand coded when the code is written and so it means that the value reflects the date/time when the code is written rather than when it runs and the object is created.</p>
<p>While this is not really a big issue here, it does illustrate a wider point. The nature of JavaScript is really that the code is run and therefore the objects are created when a user loads the web page or indeed when the page is refreshed. This is something you need to bear in mind when dealing with an object like Date and you really need to consider what Date you want to store and this will determine which approach is best. However, I would imagine it that we will see a better way to store data like this either later in the course or perhaps in another course geared towards the creation of web apps.</p>
<p>It might be worth taking a few moments to consider the <ahref="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date</a> object. Date objects contain a number which records the date in epoch time (that is, since 1 January 1970) in milliseconds. In essence, it stores the number of milliseconds that have elapsed since that date. That's why the subtraction in the backpackAge function returns a value in milliseconds.</p>
<p>One of the functions available to Date is the toString function which returns a Date object as a string and I guess that Morten's version of the code where he initialised the code using a string value uses this function in order to initialise the backpack object with a date sometime in the past which makes the backpackAge a little more interesting since it gives us an age for the backpack of 1028 days. In my version, we are creating the backpack object and then checking it's age straight away so it, of course, reports the age as being 0 days.</p>
<p>Another interesting point here is that the age of the backpack in the video is 670 days so given it's dateAcquired property which shows the object was created on 5 December 2018, this allows us to work out what the actual date was when the video was being recorded, assuming that it was recorded on the same day that Morten ran the code to calculate its age!</p>
<h2class="sectiontitle">Challenge: Create a New Object Type</h2>
<p>For this challenge, we want to create at least five Book objects and each object must have at least one property and at least one function. Any method by which objects can be created may be used, but I will create a Book class to define the class and another file in which objects are created.</p>
<p>My solution to the challenge has been created as 2 JS files called Book.js and script.js to create the class and the instances respectively. In order to make them accessible via the browser, I have also created an HTML file called <ahref="codesamples/chapter3/book.html">book.html</a>.</p>
<p>The code for all three files can be seen in book.html along with the output.</p>
<p>For functions, I decided to create several different possible values for status and several functions to update the status. For example, if a book has a status of "on shelf", I can use the startBook function to update the status to "reading", if the status is "reading", I can use the finishBook function to change the status to read.</p>
<p>Note that I am not doing any error checking or status checking so these functions will simply set a new status regardless of what the current status is so, for instance, if the current status is "read" and the startBook function is used, the status will simply be set to "reading". If this were a real application, I would probably want to check the status to verify whether a function makes sense. An example of this might be preventing the startBook function being used where the current status is "loaned".</p>
<p>However, this is just intended to be a very simple example and the functions demonstrate the use of functions with a class perfectly well.</p>
<p>One point of interest from the solution to this challenge is that I have included a property called pub_date which holds the year of publication and since it is just the year, I have implemented this as an integer (I did something similar with my CD class). Morten's solution also includes a property representing the year of publication, but he implemented this as a string. The reason for this is that there may be a reason at some point to use this with a Date object and, as it happens, Date objects tend to work better with strings so that is something to bear in mind.</p>