You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
35 KiB
211 lines
35 KiB
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 the JavaScript Language")); |
|
heading.append(addParagraph("Joe Chellman - LinkedIn Learning - May 2023")); |
|
heading.append(addParagraph("Objects, Arrays and More")); |
|
|
|
main.append(addHeader("Objects")); |
|
main.append(addParagraph("Not surprisingly, objects in JavaScript use JSON which is certainly not restricted to JavaScript but it is JavaScript Object Notation. The simplest form of an object is an empty object which is written as {}.")); |
|
main.append(addParagraph("If it is not empty, an object will be made up of a series of one or more key value pairs and, of course, the usual JSON rules apply but the key doesn't have to be be enclosed in double quotes although it probably should because that would be compatible with standard JSON.")); |
|
main.append(addParagraph("The value can be any type of value such as a string, a number or something more complex like an array or even an object. You can get a comprehensive JSON Cheat Sheet from https://www.hostinger.co.uk/tutorials/what-is-json.")); |
|
main.append(addHeader("Using Objects for Data Modelling")); |
|
main.append(addParagraph("This is really the point of objects, they allow us to model real world objects by creating an abstraction of that object. For example, let's the object is a bird. We might create an object like this.")); |
|
main.append(addSyntax(" main.append(addImageWithCaption(\"./images/bird.png\", \"The code to create a bird object.")); |
|
main.append(addParagraph("I think it is important to remember that while an object can be used to model a physical object like a bird or a bear, it can also be used to model something a bit more abstract.")); |
|
main.append(addParagraph("As an example, I am always looking at ways in which I can automate as much as possible the process for creating pages for this site. To give an example, the menus at the top of the page are generated by a couple of function calls. The first is to global_menu() which generates the menu on all of my pages. The second is to local_menu() which generates the menu specific to this course.")); |
|
main.append(addParagraph("The global menu is pretty much fixed and each page just needs to call the function with a command like")); |
|
main.append(addSyntax("global.append(global_menu());")); |
|
main.append(addParagraph("The second is sort of similar but it passes an argument to local_menu() identifying the course. When I write the code to generate this page, for instance, the call will look like this.")); |
|
main.append(addSyntax("local.append(local_menu(\"learningthejavascriptlanguage")); |
|
main.append(addParagraph("The function is in a script called webdev.js and it takes the argument and uses it to look up the titles and the href values for the menu links and generates the menu which is appended to the area of the grid labelled local.")); |
|
main.append(addParagraph("This is pretty much an automated process, I just need to set up the arrays in webdev.sys to generate those links and it will add the menu to the page. A minor issue with this is that if I want to change the value used to call the menu, that has to be done in every page for the course.")); |
|
main.append(addParagraph("There are also a few other areas where a change has to be applied to every page and it's not really a huge problem. However, I am always looking at ways to improve this process and I don't really use objects at the moment, but that might be one way to do that. ")); |
|
main.append(addParagraph("It occurs to me that I could use an object for each course that includes the menus, the data displayed in the titles and so on and import it as required. That means that the function calls can be more generic so the call to local_menu() will get the value needed to make the call from the object. It will also include other things like a link to the course, course title, lecturer and so on so this means that if any of these details need to be change (such as when I find that the title has been mis-spelled), I only need to change it in the object and the only call that I need to add to every page is going to be a call to an object. This is only an idea at this point and I haven't actually implemented it yet as I type this but by the time it makes it to the website, this page will (I hope) be generated using an object to hold the course details.")); |
|
main.append(addHeader("Manipulating Objects")); |
|
main.append(addParagraph("We can access the properties of an object using dot notation in the format")); |
|
main.append(addSyntax("object.property")); |
|
main.append(addParagraph("For example, we can open a console in the Firefox Web Developer Tools and paste in the line of text that creates the bird object and access the quote property with")); |
|
main.append(addSyntax("bird.quote")); |
|
main.append(addParagraph("The result is shown below.")); |
|
main.append(addImageWithCaption("./images/bird1.png", "Accessing one of the properties of the bird object.")); |
|
main.append(addParagraph("One thing to note here is that although it is usually best to enclose a string in quote marks (which we did when creating the bird object) we will get an error if we do that when accessing the properties. You might not think of that as a problem and it won't be if you don't use embedded spaces or other special characters in your key.")); |
|
main.append(addParagraph("If you do, there is an alternative notation that allows you to specify the property as a string by enclosing the property in square brackets like this. In this instance, we will omit the dot so this is an alternative to do notation.")); |
|
main.append(addSyntax("bird[\"quote\"];")); |
|
main.append(addParagraph("We can also add properties using either notation. For example, let's say we want to add a colour property with a value of black, we can use dot notation.")); |
|
main.append(addSyntax("bird.colour=\"black\";")); |
|
main.append(addParagraph("Let's say we want to add another property called \"where it lives\" and we will give that a value of \"in a tree\". Notice the key has some spaces so we will need to use the square-bracket notation like this.")); |
|
main.append(addSyntax("bird['where doesit live'] = \"in a tree\"")); |
|
main.append(addParagraph("The image below shows this in the console to demonstrate in particular the square-bracket notation.")); |
|
main.append(addImageWithCaption("./images/bird2.png", "Two different ways to access the properties of an object and to add properties to an existing object.")); |
|
main.append(addParagraph("It may be worth noting that while this square-bracket notation allows you to use a property name like 'where does it live', this is probably not good practice and it is better to use a more conventional approach to naming the keys such as using an underscore (or hyphen if you really must) or you can use camel-case notation.")); |
|
main.append(addParagraph("So we can very easily add properties to an object by creating a name for it and assigning it a value in one statement. We can also remove properties and we would use the delete command for that, again with either notation so we can remove the colour property with")); |
|
main.append(addSyntax("delete bird.colour;")); |
|
main.append(addParagraph("or ")); |
|
main.append(addSyntax("delete bird[colour] ")); |
|
main.append(addParagraph("and the 'where it lives' property with")); |
|
main.append(addSyntax("delete bird['where it lives']")); |
|
main.append(addParagraph("Note, we started off by describing how you could create an empty object and while I'm not sure whether you would ever want to do that, you can and you can then add and remove properties using this notation.")); |
|
main.append(addHeader("References")); |
|
main.append(addParagraph("When you create on object in JavaScript and you use a reference to hold the value such as we did when we created the bird object (bird is the reference), it is important to know that this is not quite the same thing as making the bird variable equal to the object.")); |
|
main.append(addParagraph("In this case, bird is a reference to the object. Is this an important distinction?")); |
|
main.append(addParagraph("Actually, it is and you will see why if you execute a command like this:")); |
|
main.append(addSyntax("bird2 = bird1;")); |
|
main.append(addParagraph("If you have programmed before, you may think that this is creating a second variable called bird1 and giving it the same value as bird. If you run a command such as")); |
|
main.append(addSyntax("bird2.commonName;")); |
|
main.append(addParagraph("for instance, you will get the same output as you would with")); |
|
main.append(addSyntax("bird.commonName;")); |
|
main.append(addParagraph("You can see this in the image below.")); |
|
main.append(addImageWithCaption("./images/reference.png", "Both bird.commonName and bird1.commonName return the same value.")); |
|
main.append(addParagraph("Let's say we now update the commonName property for bird1 with")); |
|
main.append(addSyntax("bird1.commonName = \"crow\";")); |
|
main.append(addParagraph("and we check this property for both, we get the results shown below.")); |
|
main.append(addImageWithCaption("./images/reference1.png", "Both bird.commonName and bird1.commonName still return the same value.")); |
|
main.append(addParagraph("You may not have expected that result. It seems that updating the commonName property for bird1 also updated the same property for bird.")); |
|
main.append(addParagraph("Actually, that is what it looks like but that isn't really accurate and this is where the reference came in. The variable bird doesn't really hold the bird object, it actually holds the address in memory where it is stored and that's what we mean by reference. When we assigned the same value to bird1, we were assigning that same reference so both bird and bird1 now point to the same object in memory.")); |
|
main.append(addParagraph("This means that we now have one object referenced by both bird and bird1 and so when we change it, both will continue to reference the modified object.")); |
|
main.append(addParagraph("If we want to create a new object holding the same value (that is, the same properties and property values), this is a little trickier but there are several ways to do it. The mist simplistic way is to copy and paste the code used to create the original object and use it to create a new object with a different reference.")); |
|
main.append(addParagraph("We can also use the assign method")); |
|
main.append(addSyntax("bird1 = Object.assign({}, bird);")); |
|
main.append(addParagraph("and this takes all of the properties and property values of bird and assigns them all to bird1 and in many ways, you might consider this as a more sophisticated way of using our copy and paste method and the result is the same. What it actually does is it creates a new empty object, copies all of the properties of bird into this object and then sets bird1 as a reference to this new object.")); |
|
main.append(addParagraph("We can also do this")); |
|
main.append(addSyntax("bird1 = { …bird };")); |
|
main.append(addParagraph("The three dots are called the spread operator and it is basically used to spread out the properties of bird and place them in a new object referenced by bird1 and this is more or less equivalent to using the assign method.")); |
|
main.append(addParagraph("Another method we can use is to convert the object into a string and use that string which we convert back to an object which we can assign to bird1 and this us using the methods belonging to the built-in JSON object.")); |
|
main.append(addSyntax("bird1 = JSON.parse(JSON.stringify(bird));")); |
|
main.append(addParagraph("The JSON stringify method is executed first with bird as its argument and this generates our string. The parse method converts it back to an object and this value is assigned to bird1. Again, don't forget that this is a reference so we are not really assigning the object as the value of bird1 but rather its address in memory. However, the effect is the same and you might reasonably think of bird and bird1 as holding the same values as each other although in reality, they now hold different values because they both hold references to different but identical objects.")); |
|
main.append(addParagraph("Now, if we change a property for bird1, this will have no effect on the bird object and they will no longer be identical.")); |
|
main.append(addHeader("Arrays")); |
|
main.append(addParagraph("The key characteristic of an array is that it is an ordered list and in JavaScript, it is an object which means that you have methods which can be applied to them. They are also dynamic – in other words, you can append or delete items from the array.")); |
|
main.append(addParagraph("An array can consist of simple elements such as string, numbers or Booleans or more complicated elements such as arrays or objects. JavaScript doesn't support true 2-dimensional arrays although you can approximate this by creating an array of arrays but bear in mind that you can change the size of arrays dynamically and make other changes so these can't be considered proper 2-dimensional arrays.")); |
|
main.append(addParagraph("Another point is that an array will most commonly be a list of a particular type of variable or you might say a particular type of data. For example, you might have an array that contains the names of European countries and maybe an array that contains a list of the capitals of those countries. We could take this further and imagine an array containing the name of a country, its capital, it's size in square kms and so on. You can put those arrays into an array of countries so you do essentially have a 2-dimensional array.")); |
|
main.append(addParagraph("However, there is no guarantee that the array will contain sensible data so for example, one array might have 'Paris' where you expect the country name, 551,695 as the capital and 'France' as the size. You might also change one of the elements so that it contains just the string 'France' and this is probably more likely than putting the wrong data into an array element or you might give it some completely different type of value.")); |
|
main.append(addParagraph("This malleability of an array is actually quite a powerful feature but it also means, in my opinion, that you should be very careful if you do try to implement a two dimensional array and also bear in mind that there are better options.")); |
|
main.append(addParagraph("For example, you might create a class for country so when you instantiate the class, you can do some data validation to ensure that each field holds appropriate data and you can then create an array of objects.")); |
|
main.append(addParagraph("You can still make a mistake and set the value for an element in the array to something random and irrelevant but I think the main take-away from this should be that however you construct your data objects, you do need to be careful and that you can implement a two dimensional array in JavaScript but you should remember, it's not a true 2-D array and this is important because you should always remember that your array might not contain exactly the dimensions or types of data that you think.")); |
|
main.append(addParagraph("A quick side note here, that was a little bit of a random digression and well constructed code in any language can help you avoid these things by programming defensively and assuming that users will try to insert invalid data. You should therefore always (where both possible and practical) ensure that data is checked, especially if it is being input by a user before you insert it into your array.")); |
|
main.append(addHeader("Manipulating Arrays")); |
|
main.append(addParagraph("Arrays in JavaScript are largely the same as in any other programming language so they are zero indexed and elements are accessed using square bracket notation. For example, you might create an array like this")); |
|
main.append(addSyntax("countries = [\"England\", \"The Netherlands\", \"Spain\", \"France\"]")); |
|
main.append(addParagraph("Incidentally, with the knockout stages of Euro 2024 starting in 2 days, this is my prediction for the four teams that will make the semi-finals. We can access any one of these using the index value which starts at 0 so")); |
|
main.append(addSyntax("countries[0]")); |
|
main.append(addParagraph("would give you England. If I changed my mind and decided that Germany would beat France in the quarter-finals I could update the array with")); |
|
main.append(addSyntax("countries[3] = \"Germany\"")); |
|
main.append(addParagraph("Let's say I did this")); |
|
main.append(addSyntax("countries[4] = \"Germany\"")); |
|
main.append(addParagraph("In many programming languages, this would give you an error because I am trying to write to an element beyond the end of the array, but remember that JavaScript arrays are dynamic, not static, so this will just add the element to the end of the array giving us 5 predictions for the semi-finals.")); |
|
main.append(addParagraph("This is generally considered bad practice though because of the fact that the array might not have the exact length you expect so you can do this instead.")); |
|
main.append(addSyntax("countries[countries.length] = \"Germany\"")); |
|
main.append(addParagraph("Due to the fact that we start counting elements at 0, the index value of the last element will be 1 less than the length. With four elements, the index values are 0, 1, 2 and 3 for example. In this case, countries.length will return 4 so in both cases, the element will be added to the end of the array but where we use the length function rather than the number 4, this will be added to the end of the array regardless of the number of elements that it actually holds. This means you can add an element to the end of the array even if you don't know how many elements are in that array.")); |
|
main.append(addParagraph("You should also remember that a JavaScript array is an object and so it has array methods. One of these is push and it also will append an item to the end of the array so again, it allows us to add the element without needing to know the current length of the array.")); |
|
main.append(addSyntax("countries.push(\"Germany\")")); |
|
main.append(addParagraph("Similar to push is pop and this will remove the last element from the array like this.")); |
|
main.append(addSyntax("countries.pop()")); |
|
main.append(addParagraph("The image below shows these commands being run with node and notice that in most cases, I reset the value of the array before running the next command.")); |
|
main.append(addImageWithCaption("./images/arrays.png", "Experimenting with adding and removing elements from an array.")); |
|
main.append(addParagraph("Interestingly, if you use pop and push to manipulate the elements of an array, you are effectively treating it as a stack which operates on a LIFO (last in, first out) basis using push to add an element to the top of the stack and pop to retrieve the top item.")); |
|
main.append(addParagraph("There are also a couple of methods that will add or remove an element at the front of the array and these are shift (which will add an element to the front of the array) and unshift (which will remove the element from the front of the array). Notice that if you do shift an element to the front of the array, it will then have an index value of 0. For instance, going back to this array:")); |
|
main.append(addSyntax("countries = [\"England\", \"The Netherlands\", \"Spain\", \"France\"]")); |
|
main.append(addParagraph("The statement")); |
|
main.append(addSyntax("countries.shift(\"Germany\")")); |
|
main.append(addParagraph("will give us this array")); |
|
main.append(addSyntax("countries = [\"Germany\", \"England\", \"The Netherlands\", \"Spain\", \"France\"]")); |
|
main.append(addParagraph("Notice that England now has an array index of 1 rather than 0 and France, which previously had an index value of 3 now has an index value of 4. Basically, every element of the array has shifted one position to the right and its index value is now one greater.")); |
|
main.append(addParagraph("Compare this with push and pop where push would have created a new element at index 4 and pop removes that element, but the other elements do not change their index values. It might occur to you that if you use shift and unshift together you are creating a stack which is fair enough, you are just operating on the other end of the array but the effect is the same.")); |
|
main.append(addParagraph("If we mix these and use push with unshift on an array we would effectively have a FIFO (first in, first out) collection or a queue and similarly using shift and pop together would give you a queue in the opposite direction. It is important to remember that this does not strictly speaking give you a clue because there are no constraints (as far as I know) that would allow you to only permit let's say push and unshift methods for an array.")); |
|
main.append(addParagraph("In an object-oriented programming language, the way to do this would be to create an object (or class) which is declared as private and has public methods that use push to add elements to your array and unshift to remove elements. It wouldn't be possible to use any other methods on the array and you would therefore have a true queue.")); |
|
main.append(addParagraph("The same arguments apply to creating a stack which again, if you can't limit the methods that can be used to add and remove elements can't properly be considered a stack. Fur further reading, you might want to looks at the <a href=' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes'>Classes</a> reference on the MDN Web Docs. Classes in JavaScript can be declared with visibility set to private so it may be possible to implement a true queue or stack but I don't yet know enough about how JavaScript treats classes as yet to be certain.")); |
|
main.append(addParagraph("Notes – try to find out whether classes in JS can be truly private and then add a note to the above paragraph to reflect this.")); |
|
main.append(addParagraph("So it is easy to remove an element from either end of the array. What if I want to remove an element from somewhere in the middle of the array. Let's say the array is now in this state")); |
|
main.append(addSyntax("countries = [\"Germany\", \"England\", \"The Netherlands\", \"Spain\", \"France\"]")); |
|
main.append(addParagraph("and I want to remove Spain. One way to do that would be to use the delete method like this")); |
|
main.append(addSyntax("delete countries[3]")); |
|
main.append(addParagraph("If you execute that statement, you will see true being returned and if you then check the value of the array, you will see this")); |
|
main.append(addSyntax("countries")); |
|
main.append(addSyntax("Array(5) [ \"Germany\", \"England\", \"The Netherlands\", <1 empty slot>, \"France\" ]")); |
|
main.append(addParagraph("So the element hasn't been removed. Its value has been deleted but this gives the element a different value (which you may see as <1 empty slot> as shown above or undefined, depending on the environment and the array does still have 5 elements.")); |
|
main.append(addParagraph("If you want to remove the element completely, you can use the splice method. This method can be applied to an array and takes two arguments, the index value of the first element you want to delete and the number of elements to be deleted. So")); |
|
main.append(addSyntax("countries.splice(3,1)")); |
|
main.append(addParagraph("will return an array that contains the deleted elements (note, these are not stored so it is not creating a new array to hold your deleted elements). The state of the array will now be")); |
|
main.append(addSyntax("countries = [\"Germany\", \"England\", \"The Netherlands\", \"France\"]")); |
|
main.append(addParagraph("Now, the element has been completely removed and the array holds only four elements. You can find out more on the MDN Web Docs page for <a href='https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Arrays'>Arrays</a>.")); |
|
main.append(addHeader("Readability")); |
|
main.append(addParagraph("When I am creating several variables, I tend to use self-contained statements that declare and usually initialise the variable so the code might look something like this:")); |
|
main.append(addInsetCodeListing(["var year = 2024;", "var month = 'June';", "var day = 29;"])); |
|
main.append(addParagraph("You can write this more concisely as")); |
|
main.append(addSyntax("var year = 2024, month = 'June', day = 29;")); |
|
main.append(addParagraph("That is not quite as readable so you might prefer to use some whitespace to combine these two like this:")); |
|
main.append(addInsetCodeListing(["var year=2024,", "month = 'June', ", "day = 29;"])); |
|
main.append(addParagraph("Notice that the variable assignments are comma separated and since this is one statement, we do have a semi-colon but only at the end of the last variable assignment.")); |
|
main.append(addParagraph("We can also add comments both to explain the code and also make it easier to read. As with most languages, JavaScript supports both inline and block comments and these are C style comments so")); |
|
main.append(addSyntax("// this is an inline comment")); |
|
main.append(addParagraph("and")); |
|
main.append(addSyntax("/* This is a block comment")); |
|
main.append(addSyntax(" * It is spread over several lines")); |
|
main.append(addSyntax(" * Note that it starts with a slash and an asterisk")); |
|
main.append(addSyntax(" * and ends with the two characters reversed.")); |
|
main.append(addSyntax(" * It isn't necessary to have a space and an asterisk")); |
|
main.append(addSyntax(" * at the start of the line but I like this style")); |
|
main.append(addSyntax(" * because it tends to highlight the comments in")); |
|
main.append(addSyntax(" * your code a little bit better.")); |
|
main.append(addSyntax("*/")); |
|
main.append(addParagraph("This style of comment is one that I like, particularly where the comments are a large block of text.")); |
|
main.append(addParagraph("You should also bear in mind that you can convert a line or block of code to a comment as a way of troubleshooting an issue. This can be handy because it effectively removes that code from the program so you can see how it runs without it but you can also reenable the code that makes it a comment.")); |
|
main.append(addParagraph("To give you an example of that, the following line of code is in one of the JavaScript files for this site.")); |
|
main.append(addSyntax("console.log(\"This is what was passed to the function, menu!\");")); |
|
main.append(addParagraph("It's purpose is to log a line of text to the console which can be a way of making sure the block of code after it is being executed. In this case, it is in a function so if the text is logged to the console, I know that the function had been called and was doing something so this can be a very useful troubleshooting technique.")); |
|
main.append(addParagraph("If I want to disable this, but not delete in case I want to start logging this again, I can do that by making it a comment like this")); |
|
main.append(addSyntax("// console.log(\"This is what was passed to the function, menu!\");")); |
|
main.append(addParagraph("If I later remove the two backslash characters, the line of code is then re-enabled.")); |
|
main.append(addParagraph("A common source of errors is disabling a block of code that already contains a block comment. The reason this is a problem is that when you start a block comment with /*, the interpreter will read everything as a comment until it gets to end of the comment block. So it terminates the comment when it finds */ and everything after that is assumed to be valid and executable code.")); |
|
main.append(addParagraph("If you have one block comment inside another, when the comment will then terminate with the end of the inner comment and then try to interpret the rest of the comment which will most likely confuse it and give you an error. Consider this example which may make this clearer")); |
|
main.append(addSyntax("1. /* ")); |
|
main.append(addSyntax("2. This is a multi-line ")); |
|
main.append(addSyntax("3. block comment")); |
|
main.append(addSyntax("4. /* this is also a block comment */")); |
|
main.append(addSyntax("5. and this is the rest")); |
|
main.append(addSyntax("6. of the comment")); |
|
main.append(addSyntax("7. */")); |
|
main.append(addParagraph("For clarity, I have numbered the lines and you can see that the comment starts on line 1 and ends on line 7 right? However, we also have a block comment on line 4 but the /* is part of the comment since it doesn't terminate until the interpreter finds the */ characters which it finds at the end of line 4. Line 5 is therefore treated as executable code and since it is not valid JavaScript, the interpreter will throw up an error, as you can see below.")); |
|
main.append(addParagraph(" main.append(addImageWithCaption(\"./images/nested_comments.png\", \"The result of embedding one block comment inside another.")); |
|
main.append(addParagraph("Notice that the interpreter is quite happy with everything up to the end of line 4 and then we start to see errors appearing. Since inline comments end at the end of the line (they are effectively self-terminating) you won't see this problem with them.")); |
|
main.append(addParagraph("It is also worth mentioning that you may also see */ in different contexts. If the interpreter encounters these characters outside of a comment, for example in the regular expression")); |
|
main.append(addSyntax("var myRegExp = /[0-9].*/;")); |
|
main.append(addParagraph("it will be interpreted differently rather than as a comment ending but if this is in a block of code that you try to disable inside a block comment, you will run into this problem. The most effective measure against this is syntax highlighting which will normally show a comment in green. Again, an example should make this clearer.")); |
|
main.append(addImageWithCaption("./images/nested_comments1.png", "The result of embedding one block comment inside another.")); |
|
main.append(addParagraph("This is an example from the exercise files and it shows the two different types of comment. If we remove the end of the block comment, this is what happens.")); |
|
main.append(addImageWithCaption("./images/nested_comments.png2", "The result of embedding one block comment inside another.")); |
|
main.append(addParagraph("The code from line 7 onwards is now entirely in green except for the semi-colon on line 21 which is white because it comes after the end of that regex which is now being interpreted as the end of the block comment. The lines below that are ordinary inline comments so these show in green as they did in the first image.")); |
|
main.append(addParagraph("You will often see your code turning green like that when you insert a block comment and it will revert to normal when you finish the comment with its closing characters.")); |
|
main.append(addHeader("Regular Expressions")); |
|
main.append(addParagraph("In JavaScript, a regular expressions is a data type so typically, you would create a variable and give it a regex value which you can then perform functions on or with. For example")); |
|
main.append(addSyntax("var regex = /this/;")); |
|
main.append(addParagraph("You can test this by creating some string values:")); |
|
main.append(addInsetBulletList(["This is the longest string ever.", "This is the shortest string ever,", "Is this the string called Mount Everest", "This is the Sherman on the mount."])); |
|
main.append(addParagraph("This is a very simple regex which tests for the literal string, \"this\" and if we apply it to our first string with")); |
|
main.append(addSyntax("regex.test(string1);")); |
|
main.append(addParagraph("this returns false because string doesn't contain the pattern we are trying to match and this highlights an important point which is that regular expressions are case-sensitive by default so \"this\" doesn't match with \"This\" which gives us the false response.")); |
|
main.append(addParagraph("We will also get a false response with string2 and string4, but we do get a true response with string 3, which does contain \"this\".")); |
|
main.append(addParagraph("I mentioned that regexes are not case-sensitive by default and you can add a flag after the expression which will cause the regex to ignore case when trying to find a match. We use an i for this so the regex becomes")); |
|
main.append(addSyntax("var regex = /this/i;")); |
|
main.append(addParagraph("This regex will give us a true response for any of the four strings.")); |
|
main.append(addParagraph("Another way in which we can modify our regex is to put a carat (^) at the start which anchors the pattern to the start of the string.")); |
|
main.append(addSyntax("var regex = /^this/i;")); |
|
main.append(addParagraph("Remember, we are ignoring case here but because of the carat, we are only looking for \"this\" at the start of the string. This means that we now get true response from strings 1, 2 and 4 and now string 3 is the only one that gives us a false response because it does match the string, but the match is not at the start of the string.")); |
|
main.append(addParagraph("We can similarly use a dollar sign at the end to anchor the pattern to the end of the string so ")); |
|
main.append(addSyntax("var regex = /this$/i;")); |
|
main.append(addParagraph("will only match with \"this\" if it appears at the end of the string so all four of our strings will give a false response.")); |
|
main.append(addParagraph("If we change our regex to the following:")); |
|
main.append(addSyntax("var regex = /ever.$/i;")); |
|
main.append(addParagraph("This will now match with strings 1 and 2 giving a true response and will give a false response with strings 3 and 4. You may have expected this because strings 1 and 2 both have \"ever.\" at the end, but that's not quite why they match. The dot in this case is matching with any character so it would return a true response if the string had \"ever\" followed by any character at the end so it would match with \"ever.\", \"ever!\", \"every\" and so on. If we want our pattern to match only with a full stop, we would have to escape it the regex. So")); |
|
main.append(addSyntax("var regex = /ever\.$/i;")); |
|
main.append(addParagraph("will still match with \"ever.\", but will now return a false response if we have \"ever!\", \"every\" or ever followed by any other character. Note that it will not match with \"ever\", regardless of whether we escape the full stop or not. If we escape it, we will only get a match if there is a full stop after ever. If we don't escape it, it will match with ever as long as there is one (and only one) character after it and that includes a space.")); |
|
main.append(addParagraph("Regular expressions can be very powerful and can do things like extracting pieces of text that match a specified pattern, performing search and replace operations and the pattern can be much more flexible than the examples we have seen. For more information, you may want to check out Kevin Skoglund's course, <a href=' https://www.linkedin.com/learning/learning-regular-expressions-15586553'>Learning Regular Expressions</a> or Grant McWilliams course, <a href=' https://www.linkedin.com/learning/bash-patterns-and-regular-expression's>Bash Patterns and Regular Expressions</a>. You should bear in mind that regular expressions have a wide range of uses and not everything will apply in JavaScript if you are doing a general course on the subject or a course specific to another language.")); |
|
|
|
addSidebar("webdev"); |