Arrays Explained

Arrays in JavaScript are similar to arrays in other languages, but with one important differences. In most cases, such as a C array, the size of the array has to be defined when the array is first declared so if you create an array of 10 elements, it will always have 10 elements. You can change the value of each element, or you can remove a value from an element, but you can't actually remove an element or add an element.

In JavaScript, you can add or remove elements and so if you want to make a comparison with C, a JavaScript array is the equivalent of a dynamic linked list in C.

You can add or remove element from either end of an array with the following commands.

Command Function
push Adds an element to the end of an array
pop Removes an element from the front of an array and returns it
shift Adds an element to the front of an array
unshift Removes an element from the front of an array and returns it

Just to be clear here, the front of an array is the element with an index value of 0 and the back or the end of the array is the element with the highest index value. As an example, if the array has 10 elements, the element at the back of the array has an index value of 9 and if the array has n elements, the index value of the element at the back is n-1.

Arrays in Code

Although an array in JavaScript might seem like something that doesn't act like the arrays you might be familiar with in other programming languages, it does use a recognisable form of syntax. Let's look at an example of how an array is declared which covers off several important points.

	const collection = ["Piggy", item, 5, true];

The array has an identifier of collection and we can use standard array notation to access any of these elements starting from collection[0] and going up to collection[3]. We mentioned before that we cannot change the value assigned to a const and since collection has been declared with const, we can't then use it to reference a different variable whether that is a different array or any other type of value.

However, we can use any of these methods to add or remove elements to the array as long as the collection still references the same array. That being said, an array is just its contents so imagine we have the array, collection, as shown but we now want it to reference this array.

	[27, false, "flashlight", "backpack"]

This will give an error because we are trying to assign a new array to collection. However, if we replace this with

	collection[0]=27;
	collection[1]=true;
	collection[2]="flashlight";
	collection[3]="backpack";

That works perfectly well and has exactly the same effect, so bear in mind the fact that we can't assign a new value to our const array, but we can change the contents.

The collection array has four elements, and we can confirm that using the length function.

	console.log(collection.length)

If we add an element with an index value of, say, 9 like this.

	collection[9]=0;

So, we have added an element in the 10th positon and collection.length now returns 10 because the array has increased in size in order to accomodate this. If we output the contents of the array with something like

	console.log(collection);

This outputs as

	Array(10) [ 27, true, "flashlight", "backpack", <5 empty slots>, 0 ]

We have 5 elements that have values, but we also have a further 5 empty slots which are the 5th, 6th, 7th, 8th and 9th elements. If we try to access one of these elements

	console.log(collection[5]);

the output we get from this is

	undefined

So, there is a slot for an element with index position 5, but it is currently empty. Note that this doesn't mean that it has a value of zero or empty string or anything like that, it actually doesn't have any value at all and will not have a value until we assign one to it.

Just a quick aside regarding the length function, there are a couple of scenarios where it can be useful. For example, we can use it to control a for loop because the length equates to the number of elements in the array. In a for loop, for example, we might use the arrays length like this.

		for (let i = 0; i < collection.length; i++) {
		console.log(collection[i]);
	  } 

Since an array starts indexing from 0, the last index position in an array of 10 elements will be 9. The length of the array, in this example, is 10 so this means that the length of the array has the same value as then next index value after the end of the array. In other words, if we add another element to the array, its index value will be the same as the current length of the array. This might be clearer if I express it using some actual values.

Let's assume we have an array called myArray with length n ( we will assume that n is at least one so there is at least one element in the array). The index value of the last element is n-1. If we want to add a new element at the end of the array, it's index value will be n. Since we can get the value of n using the length function, that means that we can add an element to the end of the array with a command such as

	myArray[myArray.length] = "value"

We can also do that with the push method but it's probably a good idea to be aware of this at least because it shows how we can make use of the array length.

Array Methods

Arrays are used quite commonly in JavaScript and there are a lot of methods that you can use with them. These include both static (that is, class) methods and instance methods and they are documented in the MDN Web Docs. We will look at some of the more useful methods here and to help demonstrate these, we will use the following code and amend it as required.

	let backpackContents = ["piggy", "headlamp", "pen"];
	
	console.log(backpackContents);

The join Method

The array, shown above, contains three elements but sometimes we may want to output the entire array as a string and we use the join method for that. This is passed to the array object using standard dot notation so if we use this with the backPack contents array, that will look something like

	console.log(backpackContents.join());

The output we get from this is

	piggy,headlamp,pen

Notice that the elements have been converted into a single comma separated string without any spaces. We didn't pass it amy arguments, but we can pass it a string argument and that string will act as the separator. For instance, let's say we want the separator to be a comma and a space. We can amend the statement

	console.log(backpackContents.join(", "));

This time, the output is

	piggy, headlamp, pen

We can pass the method just about any string as a separator such as " | " or " "

shift and unshift

These methods were mentioned before but I will just mention the syntax here briefly. As a reminder, both of these methods remove an item from the end of the array, pop removes the last element and shift removes the first element. So

	backpackContents.unshift();

removes the first element which is "piggy". It is worth noting that if we use shift in this way, "piggy" has now effectively been deleted so there is no way to retrieve it other than by using the same string literal again. This means that if we want to put it back on the front of the queue, we would use the shift method like this.

	backpackContents.shift("piggy");

However, I mentioned earlier that unshift doesn't just remove the first item, it also returns it. This means that we can assign it to a variable. For example, let's assume that we have previously declared a variable called front with an appropriate declaration. We can use shift like this.

	front = backpackContents.shift();

If we want to put it back to the front of the queue, we can do that with

	backpackContents.unshift(front);

As an alternative, we could also push it back on to the back of the array with

	backpackContents.push(front);

The amended code now looks like this.

	let backpackContents = ["piggy", "headlamp", "pen"];

	console.log(backpackContents);

	front = backpackContents.shift();
	console.log("Shifted piggy", backpackContents);

	backpackContents.push(front);
	console.log("Front = ", front);
	console.log("Pushed piggy", backpackContents);

and the output we get in the console for the final version of the array is

	Pushed piggy Array(3) [ "headlamp", "pen", "piggy" ]

With both push and shift, we can add more than one element at a type by passing a comma separated arguments list to the method. To see how this works, consider this example.

	let backpackContents = ["piggy", "headlamp", "pen"];

	let first = backpackContents.shift();
	let second = backpackContents.shift();

	backpackContents.unshift(second, first);

	console.log(backpackContents);

In both cases, shift removes and returns the first element of the array, so

	let first = backpackContents.shift();

removes "piggy" and therefore the variable first references "piggy".

	let second = backpackContents.shift();

is also removing the first item, but since "piggy" has already been removed, "headlamp" is now at the front of the queue and so second references "headlamp" so these two variables now hold the first and second elements, respectively, from the original array. We can put these back with a single unshift command like this.

	backpackContents.unshift(second, first);

Note that unshift preserves the order of these arguments which might not be what you would expect. What I mean by this is that if second is unshifted and then first, you would expect the array to have the same order as the original since first was the last element to placed at the front of the array. What actually happens is that the JS interpreter treats first and second as a mini-array and places that array in the appropriate number of elements at the front of the queue (2 in this case). The result is an array that looks like this.

	Array(3) [ "headlamp", "piggy", "pen" ]

So, the effect of this little piece of code is to swap the first two elements around. The important point to remember is that the order in which these elements appear at the front of the array is the same as the order in which they appear in the arguments list.

Before moving on, I just wanted to note that pop and push have really only been mentioned in passing, but they are more or less interchangeable with shift and unshift and the syntax is the same. The following code snippet demonstrates the use of both pop and push.

	let backpackContents = ["piggy", "headlamp", "pen"];

	let third = backpackContents.pop();
	let second = backpackContents.pop();

	backpackContents.push(second, third);

	console.log(backpackContents);

This is the same as the previous example in which we swapped the first two elements of the array. This time, we are working on the back end of the array and the result we get is

	Array(3) [ "piggy", "headlamp", "pen" ]

This time, the last two elements haven't been swapped and this is because we now want the variable referenced by second to be the last element, so it needs to be last in the argument list like this.

	backpackContents.push(third, second);

It may also be worth noting that if we use shift and unshift with an array, the array is behaving like a queue. Converesly, if we use pop and push, the same array is behaving like a stack so we can use an array as an implementation of either a queue or a stack. However, there is nothing preventing you from using the wrong method such as adding or removing something at the front of a stack so this is probably not a safe way to implement either.

Just a quick digression on this. I don't know if JavaScript provides any more advanced collection types which may be better suited to the implementation of either a queue or a stack or of there is some library that provides that functionality. Assuming it doesn't, the best way to implement them is probably via a class.

For example, you might have a class called Stack which has methods for adding an item onto the back of the stack or removing an item from the back. These methods won't be push and pop, you would probably give them names like addItem and removeItem. Internally, the implementation of the stack is almost certainly be done with an array and we would use push and pop in the addItem and getItem methods, but if we don't provide any methods implemented with shift and unshift, there is no way for you to add or remove elements from the front of a Stack object and so this is a much more reliable method of implementing a stack.

Of course, if you are working with instances of a class such as Stack, you don't care whether it uses push or pop or some other methods to implement functions like addItem or removeItem, you only need to know what methods the class provides (in other words, you need to know about addMethod and getMethod, what they do, what arguments can be passed to them and what they return, but you don't need to know about push and pop and how they work. This is a kind of an oblique reference to the classes interface, the face that it presents to the outside world and it's a nice demonstration of the fact that you can use classes in order to create an abstraction that implements the features you need but not the features that you don't need.

For further information, you may want to check out one of the online tutorials such as JavaScript Program to Implement a Stack on programiz.com or Implementation of Stack in JavaScript on geeksforgeeks.org

foreach

The array methods we have seen so far are methods that operate on or involving individual elements of the array such as adding or removing an element. Some methods are designed to work on the whole array. For example, let's say that we want to take each element of our backpackContents array and generate some HTML items by adding <li> tags to them. We can do that with a for loop, but with an array, we can also make use of a specialised loop which is designed to iterate over the elements in an array.

Since it is an array, method, it is passed to an array as a function, with the function being the code that you want to execute on the array elements and a variable that acts as the this value. We saw the this value in the chapter on classes. When you write a class method, this is used to reference the current object and it plays the same role here. An example may make things clearer.

	let backpackContents = ["piggy", "headlamp", "pen"];

	backpackContents.forEach(function (item) {
	  item = `<li>${item}</li>`;
	  console.log(item);
	});

Here, we have used item as the variable name and so for each iteration of the loop, item will reference the array element. The foreach loop is taking each element in turn amd modifying it by adding link item tags and then outputting it to the console. After the loop terminates, we then output the array to the console to see how it has been changed (spoiler alert, it hasn't). The output we get is

	<li>piggy</li>
	<li>headlamp</li>
	<li>pen</li>
	Array(3) [ "piggy", "headlamp", "pen" ]

As you can see, each element of the array is displayed with the <li> tags, but the array itself is unchanged. Although we used and modified each element of the array, the changes were never sent back to the array. We can't write the item into the array because we are not using an index value for each item. However, we can introduce a variable to act as a index like this.

	let backpackContents = ["piggy", "headlamp", "pen"];

	let counter = 0;

	backpackContents.forEach(function (item) {
	  item = `<li>${item}</li>`;
	  backpackContents[counter]=item;
	  counter++;
	});

	console.log(backpackContents);

The variable is called counter and it has been given an intial value of 0 which is the index value of the first element. We use that to write the amended element back to the array using the same index and then incrementing counter so that it has the correct index value for the next element. Note that the counter variable is not controlling the loop so we don't need to check its value in order to terminate the loop (that is, we don't need some condition like counter < 3 which we would need if it was controlling the loop.

Let's look at another example of a method that operates on an array.

	let backpackContents = ["piggy", "headlamp", "pen"];

	let longItems = backpackContents.find(function (item) {
	  if (item.length >= 5) {
		return item;
	  }
	});
	console.log("longItems:", longItems);

	console.log(backpackContents);

In this example, we are using the find method on our array and it looks pretty similar to foreach in that we pass a function with an item argument to the array so once again, item will represent the this variable in the loop. And yes, it is essentially a loop because what it is doing is iterating through the array, checking the length of each element and returning the element if the is greater than or equal to 5. Once it locates an item that matches this criterion, it will terminate - strictly speaking, it is the act of returning a value that terminates this loop.

The part of this example that perhaps looks the strangest is the let longitems. If we omit this, the code would still work. This would mean changing the line that starts with let longItems to

	backpackContents.find(function (item) {

The problem with this is that the item variable only exists inside the loop so when it has finished executing, we have no way of accessing it. Clearly, it doesn't make much sense to have the function locate an item if we can't then access it although we might also amend the code to output a statement with the found item.

In order to make it accessible - bear in mind that the thing that we are trying to make accessible is the value returned by the function - we need to assign it to some variable and that is exactly what let longItems is. We are declaring a let variable, naming it longItems and then assigning it the value returned by the find function. As a matter of interest, you might be tempted (I certainly was) to try declaring a variable called item outside of this function call but this doesn't work because the item variable passed to find is locally scoped so you would just be declaring a variable with the same name and a different scope.

However, we can declare a variable beforehand to hold the item found that matches the criteria. We would then just need to set its value to item inside the function and return it instead of item. Let's say we call our variable result and declare it with let, the code might look something like this.

	let backpackContents = ["piggy", "headlamp", "pen"];
	let result;

	backpackContents.find(function (item) {
	  if (item.length >= 5) {
		result=item;
	  return result;
	  }
	});
	console.log("Result:", result);

	console.log(backpackContents);

THat works perfectly well too. The key point to take from this is that if a function returns a result, we need to have some way of storing that result if we want to use it after the function has completed and we can do that either by returning the value in the form of a variable we have created for the purpose (like result) or by creating an assignment statement with a variable on one side and the function itself on the other so in this case, we are assigning the value to a variable after it has been returned rather than assigning the value to a variable and returning the variable.

In my opinion, the first method is a little bit clearer and easier to understand whereas the second is probably a little bit more concise but both achieve exactly the same result.

Challenge: Build and Modify an Array

To complete this challenge, we need to carry out the following steps.

1. Create an array with at least 5 or 6 items.

2. Try adding and removing items using pop, push, shift and unshift with at least one example of each and for both push and unshift, have some examples of doing this with 1 and multiple items.

3. Move the last item to the first position.

4. Sort the items alphabetically.

5. Find a specific item in the array.

6. Remove an item with specified content from the array.

At least one of the tasks here involves using a method we haven't seen before, but part of the reason for having this challenge is to get you used to looking up the docs online so we will need to refer to the MDN Web Docs for Array.

Solution: Build and Modify an Array

This is my solution. When it is finished, I will check Morten's solution and add on any additional notes if needed. I will create a script in Visual Studio Code in which I will create an array and then add one command at a time to manipulate the array. The final statement will log the array to the console so we can see its state at every step.

I will start by creating and outputting the array.

	const myArray = ["html", "css", "linux", "perl", "c", "android"];

	console.log(myArray);

So, for the array I have chosen a list of interesting topics you might want to learn about in LinkedIn Learning and the output in the console is

	Array(6) [ "html", "css", "linux", "perl", "c", "android" ]

I will then remove the first and last elements using shift and pop, the order doesn't matter and this will remove html and android.

	myArray.pop();
	myArray.shift();

	console.log(myArray);

	OUTPUT: Array(4) [ "css", "linux", "perl", "c" ]

Actually, I am still interested in html but not so much android so I will put html back and add php using push and unshift.

	myArray.unshift("html");
	myArray.push("php");

	console.log(myArray);
	
	OUTPUT: Array(6) [ "html", "css", "linux", "perl", "c", "php" ]

So the array is back up to 6 items. Just as a side note, I will remove html again and then put it back, but I will use a variable to hold it so this would have the same effect regardless of what the first element in the array was.

	let first = myArray.shift();
	myArray.unshift(first);

	console.log(myArray);

So, first is initialised with whatever the first element currently is in the array and at the same time, that element is removed from the array (we are making use of the fact that shift removes and returns the first element). We then use unshift with the same variable and this puts the value we previously initialised first with back at the front of the array.

Side note: if you wanted to remove the second item from the array, there is a better way to do this but you could also do it using the above method and then shifting the next element out of the array before putting first back.

The next thing we want to do is to expand our interests further by using push and unshift to add multiple items at the same time. In both case, I will add two items because adding more is simply a matter of increasing the number of comma separated arguments.

	myArray.push("apache", "nginx");
	myArray.unshift("node", "react");

	console.log(myArray);

	OUTPUT: Array(10) [ "node", "react", "html", "css", "linux", "perl", "c", "php", "apache", "nginx" ]

I am now going to move the last item, currently nginx, and put this to the front of the queue and this is almost identical to the way we used a variable to remove and then put back the first item except that we are taking the last value, but we are putting it back in the same way. A variable isn't really required because you can just use the literal value, nginx, but if you are writing code like this in a real world application, in almost all cases you won't know ahead of time what these values are so it makes sense to get into the habit of doing this like a programmer. For example, you might want to write a function called toFront that can do this for any array.

	let last = myArray.pop();
	myArray.unshift(last);

	console.log(myArray);

	OUTPUT: Array(10) [ "nginx", "node", "react", "html", "css", "linux", "perl", "c", "php", "apache" ]

We can see there that ngimx has now moved to the front of the queue and if we wanted to, we could reverse this by using a variable to remove the first element which we would then put to the back using the push command. It might be worth noting that functions are covered in the next section which has its own challenge. As an extra challenge, you might consider writing some functions that can perform operations such as moving the first item to the back of the queue and so on or converting an array of elements to a specified type of html element by adding appropriate tags.

The next step in the challenge is to sort the elements alphabetically. This is one of those commands that hasn't been covered in the course so we may need to look it up in the online docs, but I am going to take a guess that the method is called sort and that it will sort alphabetically by default so it won't need any arguments.

	myArray.sort();
	
	console.log(myArray);
	
	OUTPUT: Array(10) [ "apache", "c", "css", "html", "linux", "nginx", "node", "perl", "php", "react" ]

It may be worth noting that if you are using an IDE like Visual Studio Code as I am, you will quickly see if sort is a valid method name because it will appear in the list of auto-suggestions. It did, and it has worked as expected.

In this case, it wasn't necessary to consult the documentation but the sort function can be more complex than this. For example, you can set it up to call a function that defines the sort criteria so even if you can guess how a function works, it is often worth checking the docs for more information on how it works. In this example, that means getting in to how functions work in JavaScript so I will leave that for now.

Next, we want to find something in the array according to some specified criterion. I will search for an item with node in the name and to do this, we will use a functon similar to one seen in an earlier example where we searched for an item with a length of 5 or more. Rather than just return the item, I want to return the value of its index which in this case is 6.

	let term=myArray.find(function (item) {
		if (item == '*node*') {
			return index;
		}
		index++;
	  });

	console.log('The index value of', term, 'is', index);

	OUTPUT: The index value of node is 6

Notice that I have made use of the fact that we can assign a value from the function to a variable and also return a value which can be quite useful.

The final part of the challenge is to remove an item so I will try to remove node using the index returned from the function above. This time, I have consulted the online docs and I can see that there is an option to remove an item by index position so and that uses the splice method with two arguments, the index value and an optional argument specfying the number of elements to remove. Although it is optional, if you omit it, everything from the specified position to the end of the array is removed (which would be 4 elements in this example so you need to be careful with this.

	removedItem=myArray.splice(index, 1);

	console.log(myArray);
	
	OUTPUT: Array(9) [ "apache", "c", "css", "html", "linux", "nginx", "perl", "php", "react" ]

We can see that our 10 element array now has 9 elements so 1 was removed and node is missing so the correct element was removed.

That is the end of the challenge so I will finish off by showing the entire scripe below together with its output

	/**
	 * Challenge: Build and modify an array
	 * - Build an array with 8 items
	 * - Remove the last item
	 * - Add the last item as the first item on the array 
	 * - Sort the items by alphabetical order
	 * - Use the find() method to find a specific item in the array
	 * - Remove the item you found using the find method from the array.
	 */

	const myArray = ["html", "css", "linux", "perl", "c", "android"];

	myArray.pop();
	myArray.shift();

	myArray.unshift("html");
	myArray.push("php");

	let first = myArray.shift();
	myArray.unshift(first);

	myArray.push("apache", "nginx");
	myArray.unshift("node", "react");

	let last = myArray.pop();
	myArray.unshift(last);

	myArray.sort();

	let index = 0;

	let term=myArray.find(function (item) {
		if (item == 'node') {
			return index;
		}
		index++;
	  });

	console.log('The index value of', term, 'is', index);

	removedItem=myArray.splice(index, 1);

	console.log(myArray);
	
	OUTPUT: The index value of node is 6
			Array(9) [ "apache", "c", "css", "html", "linux", "nginx", "perl", "php", "react" ]

There are a couple of points I want to mention about Morten's solution. In the video in which the challenge was introduced, he mentioned that you could nest functions inside functions which I didn't really do. This means, for example, that we can perform an action like taking an element from the front of the array and putting it at the back without using a variable. Using the same syntax that Morten uses, this means that the code to do this would look like this.

	myArray.push(myArray.shift());

or to take the last element and put it at the front, we would do this.

	myArray.unshift(myArray.pop());

With regard to sort, it doesn't quite sort items alphabetically by default, it does something slightly different which didn't show up in the example we saw earlier and that is it sorts by (it seems) ASCII value so this means any elements beginning with an upper case letter would appear in front of any element beginning with a lower case letter as demonstrated below.

	let newArray=[ "apache", "C", "CSS", "HTML", "Linux", "nginx", "perl", "PHP", "react" ];
	newArray.sort();

	console.log(newArray);

	OUTPUT: Array(9) [ "C", "CSS", "HTML", "Linux", "PHP", "apache", "nginx", "perl", "react" ]

So, we can see that sort() gives us all of the elements starting with upper case letters in alphabetic order followed by all of the elements beginning with lower case letters in alphabetical order.

It is important to remember that this is not an error, this is just how the function works, but it does highlight a couple of intersting points. The first is that if you don't know how a funciton works, it is still worth checking the docs to find out exactly what it is supposed to do. The other, perhaps less obvious point is that when you are testing a function, you should always provide test cases for every possible scenario. In this example, if we had included one or more elements starting with an upper case letter, we may have seen in the results that it hadn't worked completely as we had intended.

When locating an element in my solution, I used an index variable, but that is not required. We can also use the indexOf function like this.

	const foundItem = deskArray.find((item) => item === "notebook");
	console.log("Found item:", foundItem);

We can also use indexOf when removing a specific element from the array with the splice method. The splice method can also accept additional arguments and Morten's full solution which is show below includes links to the online docs for the array methods used in each part of the challenge and it may well be worth checking these out.

	/**
	 * Solution: Build and modify an array
	 * - Build an array with 8 items
	 * - Remove the last item
	 * - Add the last item as the first item on the array
	 * - Sort the items by alphabetical order
	 * - Use the find() method to find a specific item in the array
	 * - Remove the item you found using the find method from the array.
	 */

	const deskArray = [
	  "pen",
	  "camera",
	  "phone",
	  "notebook",
	  "headphones",
	  "lightbulb",
	  "usb drive",
	];
	console.log("Original array:", deskArray);

	// Remove the last item:
	// @link @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
	deskArray.pop();
	console.log("New array:", deskArray);

	// Add last item as the first item on the array:
	// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
	deskArray.unshift(deskArray.pop());
	console.log("Last item is now first:", deskArray);

	// Sort items by alphabetical order:
	// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
	deskArray.sort();
	console.log("Sorted array:", deskArray);

	// Find "notebook":
	// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
	const foundItem = deskArray.find((item) => item === "notebook");
	console.log("Found item:", foundItem);

	// Find and remove an item:
	// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
	// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
	let remove = "notebook";
	deskArray.splice(deskArray.indexOf(remove), 1);
	console.log(`Array with "${remove}" removed:`, deskArray);