
Data Sets
Imagine you have the following numbers: 2, 4, 6, 8, and 10. In order to represent this collection in memory (where a computer stores information), you need a way to represent it. There is the possibility of storing the numbers in a string like "2 4 6 8 10", but it would make it extremely difficult to access the numbers and perform operations on them. For example, if you wanted to sum the numbers in the collection, you would have to split the string by a space and then add up the numbers one by one.
JavaScript provides an awesome data type that makes it very easy to work with groups of objects known as an Array. Arrays are written as lists of values surrounded by square brackets. The JavaScript representation of the collection above looks like this:
jslet list = [2, 4, 6, 7, 10]
As you may have noticed, list simply indicates the name we chose to use to store the array, so it doesn't matter what value you use. Now that we are using the list, JavaScript provides a convenient method for accessing the objects in the list. You use square brackets to locate a value in an array by its index. The term index is used to indicate the numerical position of a value in an array. Consider the following code:
jslet list = [2, 4, 6, 7, 10]// Logs 6 to the consoleconsole.log(list[2])
The code above will construct our array of numbers, store it in a variable named "list" and then log the value at index "2" to the terminal. The comment indicates that it would log "6", and you may be assuming that the value at index "2" is 4. The reason "6" is logged is that arrays in JavaScript and many (but not all) other languages is "zero-indexed". This indicates that the first item in an array can be located at index 0. So the following code will log "2" to the output:
jslet list = [2, 4, 6, 7, 10]// Logs 2 to the consoleconsole.log(list[0])
You can think of the index as the number of items to skip when starting at the first item in an array. It is also possible to put some logic in within the square brackets when handling array values. Take a look at the following code:
jslet list = [2, 4, 6, 7, 10]let index = 2let a = 5let b = -3// Logs 6 to the consoleconsole.log(list[2])// Logs 6 to the consoleconsole.log(list[1 + 1])// Logs 6 to the consoleconsole.log(list[index])// Logs 6 to the consoleconsole.log(list[a + b])
All of the console.log codes above will result in the same thing being written to the console.
Properties
Up to this point you have most likely been using a couple properties without actually understanding what they are and how they exist. For instance, if you have a string and would like to log it's length you could utilize code like the following:
jslet greeting = 'Hello World'// Logs 11 to the consoleconsole.log(greeting.length)
The .length on the end of greeting is used to access the length attribute that exists on all strings. Nearly every single JavaScript data type has an associated property. The exceptions to that policy are null and undefined. Trying to access values of those values will result in failures
In JavaScript you can access the attributes of an object in two unique ways with a dot and with angle brackets. The following code will achieve the same thing:
jslet greeting = 'Hello World'let property = 'length'// Logs 11 to the consoleconsole.log(greeting.length)// Logs 11 to the consoleconsole.log(greeting['length'])// Logs 11 to the consoleconsole.log(greeting[property])
Methods
Strings and Arrays both provide a length property. Furthermore, they both contain properties that are a function. These are referred to as methods.
jslet greeting = 'Hello World'// Logs "function" to the consoleconsole.log(typeof greeting.toUpperCase)// Logs "HELLO WORLD" to the consoleconsole.log(greeting.toUpperCase())
It is highly suggested that you use dot notation when you know the property you are looking for. The bracket notation is a little more complicated, and should be avoided for when you need to use a dynamic property using a variable like in the greeting[property] example above.
In general, strings contain the same functions, and you can read more about them on javascript official doc. Now take a moment to look at the code above. greeting.toUpperCase() calls the toUpperCase function on all Strings, and without any parameters it is able to return HELLO WORLD. Properties that contain methods are called methods for this purpose, they have access to the value to which they refer. This will be discussed in depth further on in this blog. In the meantime, know that when someone says "call the [y] function on "x" they are in fact saying that "x" has a value on it called "y" and it is a function.
Arrays in JavaScript have some very useful methods for handling data. The following code demonstrates you just a couple of functions on arrays:
jslet list = [2, 4, 6, 7, 10]console.log(list)// -> [2, 4, 6, 7, 10]list.push(3)console.log(list)// -> [2, 4, 6, 7, 10, 3];console.log(list.pop())// -> 3console.log(list)// -> [2, 4, 6, 7, 10]list.unshift(3)console.log(list)// -> [3, 2, 4, 6, 7, 10]console.log(list.shift())// -> 3console.log(list)// -> [2, 4, 6, 7, 10]console.log(list.concat([3, 4]))// -> [2, 4, 6, 7, 10, 3, 4]console.log(list)// -> [2, 4, 6, 7, 10]list = list.concat([3, 4])console.log(list)// -> [2, 4, 6, 7, 10, 3, 4]
- The
pushmethod inserts values to the end of an array - The
popoperation removes the last value in an array and returns it - The
unshiftoperation adds values to the beginning of an array - The
shiftoperation removes the first value in an array and returns it - The
concatmethod combines two arrays together and returns a new array (not changing either array)
The names of the methods may be confusing/seem not intuitive. However, they are based on programming operations for stacks and queues. A stack is a common programming data structure that allows you to push and pop values in a Last In First Out (LIFO) pattern. A queue is a structure that uses a First In First Out (FIFO) pattern.
Objects
Now you have a decent amount of experience with Strings and Arrays in JavaScript. However, what if you need to represent a set of arbitrary data. Say for example you have a blog post. The posts consists of a title, category, body, and a list of tags. It would be awfully difficult to represent a post using any of the data types you currently know. This is where objects come in. Objects are arbitary collections of properties. Representing the post as an object is fairly simple:
jslet post = {title: 'Welcome To My Blog',category: 'Announcements',body:'Hello and welcome to my blog. I will be posting about my adventures as a developer',tags: ['JS', 'CSS', 'HTML'],}console.log(post.title)// -> 'Welcome To My Blog'console.log(post.tags[1])// -> 'CSS'
The above code organizes the post into a logical collection of properties. Note that it is possible to nest objects as properties of other objects, etc. In the above vode tags is an Array as a property on post. The notation used above is called "object literal" notation. You will see further in this course that there is more than one way to create an object in JavaScript. Object literal notation starts with braces:
jslet myObject = null
Inside the braces there is a collection of properties separated by commas. Each property has a name followed by a colon and a value.
jslet myObject = {propA: 'value a',propB: 'value b''prop c': 'value c'};
Notice above 'prop c' is a property on myObject, but it is not a valid binding name/number so it must be surrounded by quotes. It is common to write object properties on new lines, and indent them for better readability.
Up to this point you have understood braces null to mean the start of a block of statements. Now we are introducing a new functionality in that they describe objects. While it may seem a little weird right now, in practice it's fairly easy to deal with both functionalities.
You don't always have to define all the properties of an object up front, sometimes it can be useful to assign them later. You do this with an =, similar to how you declare and assign a variable:
jslet person = {firstName: 'John',lastName: 'Doe',}console.log(person.email)// -> undefinedperson.email = 'john.doe@gmail.com'console.log(person.email)// -> 'john.doe@gmail.com'
Sometimes it can be useful to get all the properties that exist on an object, you can do this with Object.keys:
jslet person = {firstName: 'John',lastName: 'Doe',}console.log(Object.keys(person))// -> ['firstName', 'lastName']
There is also an Object.assign function that copies all properties from one object into another:
jslet person = {firstName: 'John',lastName: 'Doe',}console.log(Object.assign(person, {firstName: 'Jane',email: 'jane.doe@gmail.com',}))// -> { firstName: 'Jane', lastName: 'Doe', email: 'jane.doe@gmail.com' }
This isn't the only way to change properties on an object, you can update an object's properties with the = operator:
jslet person = {firstName: 'John',lastName: 'Doe',}person.firstName = 'Jane'console.log(person)// -> { firstName: 'Jane', lastName: 'Doe' }
Now that you know what Objects are, it is not a stretch to understand that Arrays are just a special kind of object used for storing sequences of things. In fact, Strings are also special types of objects used to store sequences of characters. So in a way Strings are like Arrays.
Object Mutability
You have observed up to this point that values in an object can be modified. Prior to now you have been dealing mostly with objects that cannot be modified, such as numbers and strings. Those are called "immutable" objects. It is not possible to change 1 to 2. Yes you can do let x = 1; x = 2, but that doesn't change 1 to 2, it simply changes x to 2. Objects are different. You can change the properties on an object, causing it to have different content at different times. Consider the following code:
jslet a = {value: 10,}let b = alet c = {value: 10,}console.log(a == b)// -> trueconsole.log(a === b)// -> trueconsole.log(a == c)// -> falseconsole.log(a === c)// -> falsea.value = 15console.log(a.value)// -> 15console.log(b.value)// -> 15console.log(c.value)// -> 10a = {value: 10,}console.log(a.value)// -> 10console.log(b.value)// -> 15console.log(c.value)// -> 10
In the above example a and b are the same object, so changing a results in a change to b as well. However setting a to a new object disconnects it from the object that is assigned to b.
