import { addBanner, addArticle, addTitle, addHeader, addParagraph, addClassParagraph, addSubHeader, addOrderedList, addUnorderedList, addBlockquote, addInset, addInsetList, addInsetCodeListing, addInsetBulletList, addImageWithCaption, addButtonGroup, addSidebar, addSyntax, menu, global_menu } from '/scripts/import.js';
import { local_menu } from '/scripts/webdev.js';
const heading = document.querySelector(".heading");
const global = document.querySelector(".global_menu");
const local = document.querySelector(".local_menu");
const sidebar = document.querySelector(".sidebar");
const main = document.querySelector(".main_content");
heading.append(addTitle("Learning ECMAScript 6 +"));
heading.append(addParagraph("Eve Porcello - LinkedIn Learning - Updated May 2024"));
heading.append(addParagraph("ECMAScript VARIABLES AND DATA STRUCTURES"));
main.append(addHeader("Using the let Keyword"));
main.append(addParagraph("The first keyword introduced to JavaScript for declaring a variable was var and it's in pretty much the same way as you would use int to declare an integer variable in C. So, you would have a command such as"));
main.append(addSyntax("var a=5;"));
main.append(addParagraph("We can now use that variable, so let's say that we want to output the value to the console."));
main.append(addSyntax("console.log(\"The value of a is \", a)"));
main.append(addParagraph("If you want to experiment with this, you can do that by putting it into a script and attaching it to an HTML file, adding it to an HTML file inside a script tag or you can just type these commands directly into the console and you should see the output telling you that the value of a is 5."));
main.append(addParagraph("There are now also a couple of other methods to declare a variable such as the let keyword, but before we introduce that, I want to look at a more complex use of the var keyword which will help to demonstrate the difference between the two. If you click here, this will open a new tab which shows you the code but it also has that code in a JavaScript tag so you can open up the console to see the result."));
main.append(addParagraph("Let's just briefly explain what the code is doing first. Fiirst, we are creating a variable called, using the var keyword, and setting its value to JavaScript. Next, we create a block of code that executes based on the conditon that the topic variable exists. Inside the block, we create the topic variable using var again, we set its value to ECMAScript and we log it to the console with the command:"));
main.append(addSyntax("console.log(\"block\", topic);"));
main.append(addParagraph("So that will tell us what value topic has inside the block. When the block terminates, we output its value again with the command"));
main.append(addSyntax("console.log(\"global\", topic);"));
main.append(addParagraph("Similarly, this will tell us the value that topic has outside the block. The reason we do this is because we want to know if the variable declaration inside the block applies only inside the block. In other words, when we set the value of topic inside the block to ECMAScript, does this overwrite the value outside of the block. If we run the code, in the output we see the result shown in figure 1."));
main.append(addImageWithCaption("./images/var_topic.png", "Figure 1 - the value of topic displayed as a block and then a global variable."));
main.append(addParagraph("So, the value of topic is ECMAScript in both cases. Before I go into the reason for this, we will change the code so that the variable in the code block is declared with let rather than var. The code for this is shown here and when we run this, we get the results shown in figure 2."));
main.append(addImageWithCaption("./images/var_topic.png", "Figure 2 - the value of topic displayed as a block and then a global variable."));
main.append(addParagraph("This time, we can see that the block variable, that is the variable created inside the code block, has the value ECMAScript, but the value of the global variable, the variable declared and created outside of the block, hasn't changed and still shows a value of JavaScript."));
main.append(addParagraph("The difference in behaviour is a result of the variables scope. A variable declared with var has a global scope which means that it is visible from anywhere in the JavaScript file. On the other hand, a variable declared with let has block scope and so it is only visible in the block in which it was created. In practical terms, since both declarations were made with global scope in the first example, we can consider these to be the same variable. In the second example, we declared the first instance of the variable with global scope and the second with block scope. As a result, when we set the value of the second instance to ECMAScript (remember, that's our block-scoped variable), it had no effect on the first instance since that declaration was made outside of the code block containing the second instance."));
main.append(addParagraph("An important point to remember, however, is that global scope and block scope can sometimes be the same thing. Think of it this way. A JavaScript file is a code block. Within that, we can create other code blocks and we can think of this as being part of a hierarchical structure. As an example, lets's say that in our file we created another code block which might be, let's say, a while loop and inside that while loop we have another if block. In total, you can think of this as four code blocks, the file itself, the first if block, the while block and the if block inside the while block. Let's then assume that we create a variable with let inside the while block. This variable is visible anywhere within that block, including the if block inside the while block. If we create a variable with let inside the if block (either one) it is only visible inside that block. If that is the if block inside the while block, the result is that within the while block, it is only availabe inside that if block. If you try to access it from inside the while block but outside the if block, you will se an error (most likely that the variable is undefined)."));
main.append(addParagraph("We will look at a more complicated option where we are using a for loop. You can see this and the associated code by clicking here."));
main.append(addParagraph("We have added some CSS to make the output look a little better, but this is incidental. The important point is that we have a variable called div and one called box followed by a block of code in the form of a for loop. The for loop runs 5 times, each time creating a box which we see as a purple box in the HTML. We also add a function to the div element each time that opens an alert with the number of the box. The idea is that if we click the first box, we'll see 'This is box #0', if we click the second we will see 'This is box #1' and so in. In reality, we see 'This is box #5' when we click any box."));
main.append(addParagraph("Next, we want to make a little change to the code and we will look at the effect before we look at the change and we can see that by clicking here. In this instance, the loop control variable has been declared with let rather than var and when we run it, we see that the boxes now behave as we wanted them to so we see the boxes identified as box 0, box 1 and so on."));
main.append(addParagraph("Again, the difference is due to scope. By using the let keyword in the second example, we are enforcing block scope so this means that each time the block of code is executed in the for loop (we are executing this code block 5 times), each iteration has its own independent copy of the variable which only exists within the code block, but more importantly, only exists for that iteration of the code block."));
main.append(addParagraph("As a result, when the block executes for the first time, it creates the block and attaches the alert function along with the variable im which equals 0 so if we then click on the block, it fires off the alert and displays i with the appropriate value."));
main.append(addParagraph("If we compare this with the first example where we declared i with var and therefore didn't enforce block scope, each iteration of the loop was working with the same global variable and so when we then click on a block, we see the alert pop up with the same value because the variable was updated every time the loop ran with the result that i, for any of the blocks, has the same value and that is the value that terminated the block. Bear in mind that the loop runs as long as i ls less than 5 so when it reaches a value of 5, the loop ends."));
main.append(addParagraph("This might be something to be wary if, particularly if you are familiar with for loops in other languages because you don't usually have to think about the scope when you run a loop, usually because you don't use the variable outside of the loop. Since we are using the variable in what is more or less an event handler, we do have to make sure that we enforce block scope."));
main.append(addHeader("Writing Template Strings"));
main.append(addParagraph("A template string is basically a string that combines literals and variables. For example, consider the following snippet of JavaScript."));
main.append(addInsetCodeListing(["function print(firstName) {", " console.log('Hello' firstName);", "}", "", "print('Isabelle')"]));
main.append(addParagraph("We have a function called print that accepts a string argument and logs the literal string 'Hello, ' to the console followed by the string (which is stored as the variable firstName) to the console. We then call the function with the argument, Isabelle, and this gives the output"));
main.append(addSyntax("Hello Isabelle"));
main.append(addParagraph("Note that we used a comma to separate the string literal from the variable so we are passing two strings to the console.log function and these are separated by a space in the output. We could also use the concatentate operator which would mean that the expression returns a string and so we are only passing one string to console.log. The downside of this is that we would have to add a space to the string to avoid, in this case, Hello and Isabelle being output as"));
main.append(addSyntax("HelloIsabelle"));
main.append(addParagraph("This would mean that the line of code inside the print function would become"));
main.append(addSyntax("console.log('Hello ' + firstName);"));
main.append(addParagraph("This means that we have to concern ourselves with issue such as do we need to add a space and if so, where do we put it. It would be easier if we could simply format a string in such a way that we could position everything exactly where we want it inside the string and this is where a string template comes in. We can change the statement inside the function to"));
main.append(addSyntax("console.log(`Hello ${firstName}`);"));
main.append(addParagraph("A couple of things to note about this. Firstly, the string itself (the string template) is enclosed in back tickts rather than single or double quotes. Secondly, we indicate that the value of a variable should be inserted in the string by enclosing the variable name in curly braces and putting a dollar sign in front of it."));
main.append(addParagraph("A string template is quite straightforward, but note that the variable name itslf is an expression which means that we don't need to use a single variable. We could use more than one inside the curly braces. The only requirement is that it returns something that can be output as part of the string we are passing to whatever function we happen to be using. In the example shown above, the variable name, firstName, simply returns its value which is a string, Isabelle, and so that string is included in the output which again is"));
main.append(addSyntax("Hello Isabelle"));
main.append(addParagraph("The following example is a little bit more complex, but it demonstrates how flexible and powerful a string template can be."));
main.append(addInsetCodeListing(["const pre = document.querySelector(\"pre\");", "", "function createEmail (firstName, price) {", " let shipping = 5.95;", "var email = `", " Hi ${firstName}! Thanks!", " Total: ${price}", " Shipping: ${shipping}", " Grand Total: ${price + shipping}", " `;", "", " return email;", "}", "", "let email = createEmail(\"Guy\", 100);", "", "pre.append(email);"]));
main.append(addParagraph("In this example, we have a function called create email which takes two arguments, firstName and price and then formats an email (very roughly) which outputs a template string which is then added to the pre element of the HTML file. The template string is split over four lines and in the first three lines, we are adding a variable to the text. In the fourth line, we are adding the result of adding two of the variables together. In short, the email outputs a greeting using the firstName, the price which was passed to the function, the shipping amount which is hard coded into the function and actually could have been a const in this example and the total price which is calculated by adding the price and the shipping amounts together."));
main.append(addParagraph("One final point on this, we are using the $ sign as part of the variable syntax here (a variable's value being added to the string by inserting the name surrounded by curly braces and preceded by a dollar sign as in)"));
main.append(addSyntax("Total: ${price}"));
main.append(addParagraph("Since this is a monetary amount, we can include a currency symbol as part of the string literal so"));
main.append(addSyntax("Total: £${price}"));
main.append(addParagraph("would give us the price in £ sterling. If we wanted to use a dollar sign instead, we do exactly the same thing."));
main.append(addSyntax("Total: $${price}"));
main.append(addParagraph("Note that we don't need to escape the $ sign, we can just use it as is, provided it isn't followed by a variable name in curly braces, it will be treated as a string literal."));
main.append(addParagraph("So, this demonstrates quite nicely how we can use the string template both with variables and with derived data (that is, data that is calculated from the data that we have)."));
main.append(addHeader("Searching Strings"));
main.append(addParagraph("JavaScript has a number of built-in functions for searching through an array and you can explore this in a browser console. To start with, open up a console and create a variable like this. We will then use that variable to experiment with some of the methods."));
main.append(addSubHeader("startsWith"));
main.append(addParagraph("The startsWith() method takes a string as an argument and that is the string that we want to search for. If we want to determine whether our variable starts with the string, 'Ear', we can invoke the startsWith() method like this."));
main.append(addSyntax("planet.startsWith(\"Ear\")"));
main.append(addParagraph("This returns true. If we try this command"));
main.append(addSyntax("planet.startsWith(\"ear\")"));
main.append(addParagraph("the result we get is false because the method is case-sensitive. So, in this case, the startsWith method tells us whether the variable planet starts with \"Ear\" which it does oe \"ear\" which does not. As we saw, it returns a Boolean value so you could use this in a conditional statement or you could assign the returned value to another variable."));
main.append(addSubHeader("endsWith"));
main.append(addParagraph("The endsWith() function is exactly the same as the startsWith function, but compares the string you provide with the end of the string so"));
main.append(addSyntax("planet.endsWith(\"th\")"));
main.append(addParagraph("will return true and"));
main.append(addSyntax("planet.endsWith(\"s\")"));
main.append(addParagraph("will return false. This method is also case-sensitive and again, it is returning a Boolean value."));
main.append(addSubHeader("includes"));
main.append(addParagraph("Again, this is a similar method but this time it will search anywhere within the string so any value that you pass to either startsWith() or endsWith() that returns a true value, will also return a true value if you pass it to includes() so"));
main.append(addInsetBulletList(["planet.includes(\"Ear\")", "planet.includes(\"th\")", "planet.includes(\"art\")"]));
main.append(addParagraph("will all return true."));
main.append(addParagraph("In short, we get a true value if the string we pass to includes() is found in the string we pass the method to, bearing in mind that again, it is case-sensitive. Note that this is not a two way comparison so we won't get a true value simply because one string is found in the other. For example"));
main.append(addSyntax("planet.includes(\"Earth1\""));
main.append(addParagraph("because our search term includes the number 1 which is not found in the original string."));
main.append(addSubHeader("search"));
main.append(addParagraph("This is similar to the includes() method, but rather than returning a Boolean value, it returns the index position of the first character of the first instance of the string, if the string is found. For instance, if we run the command"));
main.append(addSyntax("planet.search(\"art\")"));
main.append(addParagraph("will return 1. Note that the string is an array of characters so the indexing starts from 0 and it does only find the first instance. For example, let's say that we create another variable, planetX and give it the value Eartartarth, the search string art occurs three times in the variable. If we execute the command"));
main.append(addSyntax("planetX.search(\"art\")"));
main.append(addParagraph("we still get 1 as the return value because that is, again, the first instance of art in the variable."));
main.append(addHeader("Using Symbols"));
main.append(addParagraph("Symbols are the first thing in this course that is completely new to me so rather than use the course video which is a little over two minutes long, I wanted to cover the subject in more detail so these notes are taken from watching a YouTube video called The Complete Guide to JS Symbols ES6 by Colt Steele which provides an excellent explanation."));
main.append(addParagraph(''));
main.append(addParagraph("So far, we have seen a variety of data types and these are often either primitive data types such as number, char or string or are more complex data types that are based on primitive data types. For example, you might have an attribute such as person with attributes such as name (a string), age (a number) or gender (which could be represented by a character). A symbol is a relatively new data type and it essentially is used as an identifier, as we will see in a moment."));
main.append(addParagraph("In general, with primitive data types, you can refer to them via a form of shorthand notation. For example, we might create a string like this."));
main.append(addSyntax("var name = String(\"Philip\");"));
main.append(addParagraph("Here, we are explicitly stating that this is a string variable, but we don't need to do that. We can use the shorthand version"));
main.append(addSyntax("var name =\"Philip\";"));
main.append(addParagraph("and this has exactly the same effect. With Symbol, there is no shorthand version so if we want to create a symbol, we would do it with something like"));
main.append(addSyntax("let sym1 = Symbol()"));
main.append(addParagraph("If we output the value of sym1 we will get"));
main.append(addSyntax("Symbol()"));
main.append(addParagraph("If we create a second symnol, let's say we call it sym2 and output it's value, we will get the same output. But if we try to execute the statement"));
main.append(addSyntax("sym1 === sym3"));
main.append(addParagraph("this will return false. This is because of the fact that although sym1 and sym2 look the same, they both have an associated numeric value which is different and in almost all cases is unique."));
main.append(addParagraph("We can also pass a string to the Symbol function. For example, we might create our sym1 variable with"));
main.append(addSyntax("let sym1 = Symbol(\"cat)\""));
main.append(addParagraph("If we output this to the console, we get"));
main.append(addSyntax("Symbol(\"cat\")"));
main.append(addParagraph("If we create sym2 in the same way"));
main.append(addSyntax("let sym2 = Symbol(\"cat)\""));
main.append(addParagraph("and output that, we get exactly the same output. However, if we run the command"));
main.append(addSyntax("sym1 === sym2"));
main.append(addParagraph("we again get a false value returned. Again, the variables look the same, but they each have an underlying unique value. In this case, cat is just a useful way of referencing the symbol variable for debugging purposes."));
main.append(addParagraph("For refrence, you can find thre documentation for Symbol in the MDN Web Docs. To get an idea of their use, imagine you have the following object."));
main.append(addInsetCodeListing(["let user = {", " id : 9451,"," name : 'Dominique',' city : 'Siena',"," age : 59", "};"]));
main.append(addParagraph("You may want to give this a unique id "));
main.append(addParagraph("You may want to give this object a unique id in order to track but bear in mind the fact that you may be importing the object so you may not know in advance that it already has an id and you also may not know whether this id is unique. The easiest way to give it an id would be"));
main.append(addSyntax("user.id = 123456789"));
main.append(addParagraph("If we output user to the console, we would see that it now has that id but it has overwritten the original id value which we may need. So this is where the symbol comes in. We can create a symbol with"));
main.append(addSyntax("const idSym = Symbol('id');"));
main.append(addParagraph("Note that we used 'id' as a key so we can more easily identify the key and its purpose and we can add that to the user object with"));
main.append(addSyntax("user[idSym] = 123456789;"));
main.append(addParagraph("If we output the user to the console, we see the original id is still there and we also have our symbol with the key shown."));
main.append(addSyntax("Object { id: 123456789, name: \"Dominique\", city: \"Siena\", age: 59, Symbol(\"id\"): 123456789 }"));
main.append(addParagraph("However, you should be aware of the fact that the symbol is not always visible as part of an object. For instance, the command"));
main.append(addSyntax("Object.getOwnPropertyNames(user) "));
main.append(addParagraph("returns"));
main.append(addSyntax("Array(4) [ \"id\", \"name\", \"city\", \"age\" ]"));
main.append(addParagraph("Similarly, if we iterate over the object properties with a loop, it would not be visible. However, it is not hidden and we can in fact see what symbols (if any) are associated with an object with a command such as"));
main.append(addSyntax("Object.getOwnPropertySymbols(user)"));
main.append(addParagraph("which returns"));
main.append(addSyntax("Array [ Symbol(\"id\") ]"));
main.append(addParagraph("It is possible to add a symbol to the object when creating it but you need to be careful with that. Consider the following snippet of code."));
main.append(addInsetCodeListing(["const idSym = Symbol(\"id\";)", "","let user = {", " id : 9451,"," name : 'Dominique'","' city : 'Siena',"," age : 59,", " idSym: 123456789","};"]));
main.append(addParagraph("That seems to work okay but if we output the object to the console, we get"));
main.append(addSyntax("Object { id: 9451, name: \"Dominique\", city: \"Siena\", age: 59, idSym: 123456789 }"));
main.append(addParagraph("Here, the id symbol has been interpreted as a string so it has become a property of the object but not as a symbol. We can rectify that by placing the name of the symbol in square brackets so"));
main.append(addInsetCodeListing(["const idSym = Symbol(\"id\";)", "","let user = {", " id : 9451,"," name : 'Dominique'","' city : 'Siena',"," age : 59,", " \[idSym\]: 123456789","};"]));
main.append(addParagraph("Now, outputting this to the console returns"));
main.append(addSyntax("Object { id: 9451, name: \"Dominique\", city: \"Siena\", age: 59, Symbol(\"id\"): 123456789 }"));
main.append(addParagraph("so it has been recognised as a symbol. That is just something to be careful with. The reason for this is that symbols were originally intended to facilitate the use of private properties in JavaScript and this never really happened, but it does have the result that they are less public and therefore don't show up with the standard object properties."));
main.append(addParagraph("We can also create a symbol using the Symbol.for() method and this is unusual in the context of symbols in that it will generate a symbol that is unique, but only up to a point. For instance, le's say we create a symbol with"));
main.append(addSyntax("const sym1 - Symbol.for(\"cat\")"));
main.append(addParagraph("We can output this to the console and we will see"));
main.append(addSyntax("Symbol(\"cat\")"));
main.append(addParagraph("If we create a second symbol"));
main.append(addSyntax("const sym2 - Symbol.for(\"cat\")"));
main.append(addParagraph("If we output this to the console, we will see the same result as we saw for sym1 so the two symbols look the same. We can then add a third symbol with"));
main.append(addSyntax("const sym3 - Symbol.for(\"dog\")"));
main.append(addParagraph("This time we will see a dofferent result if we output this to the console."));
main.append(addSyntax("Symbol(\"dog\")"));
main.append(addParagraph("If we execute the following command"));
main.append(addSyntax("sym1 === sym3"));
main.append(addParagraph("You won't be suprised to see that this return a false result. You might also expect a false result from"));
main.append(addSyntax("sym1 === sym2"));
main.append(addParagraph("Based on what we have already seen, you might expect this on the basis that the two symbols look the same but have a different underlying value. However, we actually get a true value returned because in this context, the underlying value of the symbol is matched to the string so two symbols will be different if they are created by passing different values to the Symbol.for() method but will be the same if we pass the same value."));
main.append(addParagraph("Let's now look at a use case which should make the purpose of using a symbol mucj clearer. Let's say that we have the following code."));
main.append(addInsetCodeListing(["const RED = ('red');", "const ORANGE = ('orange');", "const YELLOW = ('yellow');", "const BLUE = ('blue');", "const cat = ('blue');", "", "function getThreatLevel(colour) {", " switch(colour) {", " case RED:", " return 'severe';", " case ORANGE:", " return 'high';", " case YELLOW:", " return 'elevated';", " case BLUE:", " return 'low';", " default:", " console.log(\"I DON'T KNOW THAT COLOUR!\");", " }", "}"]));
main.append(addParagraph("So, this is a very simple function and a series of constants representing different threat levels and each constant has a value which is essentially a representation of the colour. If we pass one of those constants or it's value to the function, the function returns the corresponding threat level so if we pass RED or 'red' to it, it will respond with severe or if we pass BLUE, or 'blue' to it, it will respond with low. We also have another constant, cat and this happens to be called Blue so we have given it a value of 'blue'. It seems reasonable to assume that if we pass it the string, 'blue', that we are intending to refer to a threat level but we can't be 100% certain of that and if we pass it the value, cat, we certainly are not referring to a threat level. In any case, for a cat, the threat level is always high!!"));
main.append(addParagraph("So we have some ambiguity in our code and it is easy to see that the values of the constants are not unique in a code example like this, but in a real world application where you might have thousands of lines of code in a number of different files, it is easy to miss this kind of duplication. If we were to pass the function an invalid value such as cat or dog, we would want the function to return the default value which tells is the colour hasn't been recognised so that we know an error has occurred but in this case, since cat has the same value as one of the other constants, when we pass this to the function, it will return low and if we pass it the value dog, it will give us an appropriate error, provided we had given dog a value that doesn't match one of these constants."));
main.append(addParagraph("If we change the code to use symbols like this"));
main.append(addInsetCodeListing(["const RED = Symbol('red');", "const ORANGE = Symbol('orange');", "const YELLOW = Symbol('yellow');", "const BLUE = Symbol('blue');", "const cat = ('blue');", "", "function getThreatLevel(colour) {", " switch(colour) {", " case RED:", " return 'severe';", " case ORANGE:", " return 'high';", " case YELLOW:", " return 'elevated';", " case BLUE:", " return 'low';", " default:", " console.log(\"I DON'T KNOW THAT COLOUR!\");", " }", "}"]));
main.append(addParagraph("This time, we are assigning symbols to the constants we want to use with the getThreatLevel() function, in other words the values representing different threat levels. If we pass this a value of 'blue' or BLUE, we get the expected output (in this case, low) so this works exactly as it did before. However, if we execute the command"));
main.append(addSyntax("getThreatLevel(cat)"));
main.append(addParagraph("the output we get now is"));
main.append(addSyntax("I DON'T KNOW THAT COLOUR!"));
main.append(addParagraph("This is because as we know, a symbol is guaranteed to be unique so this removes and danger that we will assign a variable the same value as one of our threat and have it act as though it were one of the threat levels. The variable can still have the same value, and we can even assign it a symbol"));
main.append(addSyntax("const cat = Symbol('blue')"));
main.append(addParagraph("and we would still get the same result if we pass cat to the getThreatLevel() function. The assigned values may look the same, but because they are symbols, we can know that they are different values and more importantly, we can assign values to our constants and write the function to perform some action on them without having to worry about other variables with the same values. There are simply no naming conflicts!"));
main.append(addHeader("Writing maps"));
main.append(addParagraph("A Map is an object so we can create one with a command such as"));
main.append(addSyntax("let course = new Map()"));
main.append(addParagraph("As you might expect, it hold key value pairs and any value (primitives or objects) can be used as keys or values. A map is a kind of ordered collection in that it remembers the order in which keys are inserted. You can view the online docs for JavaScript maps on MDN Web Docs."));
main.append(addParagraph("You can add keys to the map with the set command like this"));
main.append(addSyntax("course.set(\"react\", { description: \"ui\" });"));
main.append(addParagraph("So, we have a key of React and an object as the value with the object value having a description value of 'ui'. We can output the map with a statement such as"));
main.append(addSyntax("console.log(map1)"));
main.append(addParagraph("This gives the output"));
main.append(addInsetCodeListing(["{", " \"key\": \"react\",", " \"value\": {", " \"description\": \"ui\"", " }", "}"]));
main.append(addParagraph("If we want to get the value associated with a key, you can use the get method"));
main.append(addSyntax("course.get(\"react\")"));
main.append(addParagraph("When you create a map, you can pass key value pairs to the constructor rather than add them later with set (note that if you do, you can still add more pairs later with set if you need to). The following example demonstrates this and also shows a little more of the flexibility of the map object."));
main.append(addInsetCodeListing(["", "[new Date(), \"today\"],", "[2, { javascript: [\"js\", \"node\", \"react\"] }],", "[\"items\", [1,2]]", "]);"]));
main.append(addParagraph("Notice how we have different types of value for both the keys and the values, so we don't have to restrict a map to a certain type of key or a certain type of value. If we want, we can log this map to the console and we will see results similar "));
addSidebar("webdev");