Syntax notes
To go back to the README where all the chapters are: click here.
- 6.1: Harmony, ES6, ES2015
- 6.2: Let and Const
- 6.3: Quiz: Using Let and Const(1-1)
- 6.4: Template Literals
- 6.5: Quiz: Build an HTML Fragment(1-2)
- 6.6: Destructuring
- 6.7: Quiz: Destructuring Arrays(1-3)
- 6.8: Object Literal Shorthand
- 6.9: Lesson 1 Checkup
- 6.10: Iteration
- 6.11: Family of For Loops
- 6.12: For…of Loop
- 6.13: Quiz: Writing a For…of Loop(1-4)
- 6.14: Spread… Operator
- 6.15: …Rest Parameter
- 6.16: Quiz: Using the Rest Parameter(1-5)
- 6.17: Lesson Summary
We meet our two new instructors for this lesson. Name Richard Kalehoff and James Parkes.
Harmony, ES6, ES2015 means the same thing. They’re the biggest update to the JavaScript programming language. Some of the things that has changed with ES6 is:
-
New keywords
-
Different ways of writing functions
-
asynchronous goodies
-
and more
In this course, we will explore the additions to the javascript program so we can write faster, cleaner, and more efficient code.
The lesson will be broken down to four parts.
-
❏ Lesson 1 - Syntax - changes and addition to the Javascript Syntax.
-
❏ Lesson 2 - Functions - We will investigate updates to JavaScript Functions.
-
❏ Lesson 3 - Built-Ins - We will cover new ES6 built ins.
-
❏ Lesson 4 - Developer-Fu - We will wrap things up by showing you how you can incorporate these latest updates into your next JavaScript project.
Let and Const is one of the keywords that has been added to ES6.
They explain how var isn’t perfect how the code below is one example var can get into trouble.
function getClothing(isCold) { if (isCold) { var freezing = 'Grab a Jacket!'; } else { var hot = 'It's a shorts kind of day.'; console.log(freezing); } }
What do you expect to be the output from running getClothing(false)? It would result as undefined
Hoisting is a result of how JavaScript is interpreted by the browser. Essentially, before any JavaScript code is executed, all variables are "hoisted", which means they’re raised to the top of the function scope. So at run-time, the getClothing() function actually looks more like this..
function getClothing(isCold) { var freezing, hot; if (isCold) { freezing = 'Grab a Jacket!'; } else { hot = 'It's a shorts kind of day.'; console.log(freezing); } }
Now that we understand the problem with variable and hoisting, we can use let and const to declare a variable because they’re scoped to the block, not to the function. With var, variables were either scoped globally or locally to an entire function scope.
If a variable is declared using let or const inside of a block of code which is anything within a { } , then the variable is stuck in what is known as the temporal dead zone until the variable’s declaration is processed. This behavior prevents variables from being accessed only until after they’ve been declared.
Here’s another mini quiz to understand let/const.
function getClothing(isCold) { if (isCold) { let freezing = 'Grab a Jacket!'; } else { let hot = 'It's a shorts kind of day.'; console.log(freezing); } }
if we called getClothing(false), what would we get?
In this case, there would be a ReferenceError: freezing is not defined. console.log is calling freezing, but freezing is not defined in that block.
Here they just want to remind you that let and const are only available within the block they’re declared in.
Variables declared with let can be reassigned, but cannot be redeclared in the same scope.
for example:
let instructor = 'James'; instructor = 'Richard'; console.log(instructor);
let can be reassigned in the same block so the output of this would be Richard.
Const however is slightly different. Variables declared with const must be assigned an initial value, but can’t be redeclared in the same scope, and can’t be reassigned.
So if we were to use the same example as above but with const, the output would be James.
-
var - The instructors recommend ditching var since it is bad practice to use a variable globally.
-
const - It’s best to use const because of how strict it is. You would know the identifiers won’t change throughout the lifetime of the program.
-
let - though if you need something that has to be changed later, then use let.
This section just wants you to edit the following code to use const and let rather than var.
Note
|
Don’t change the order. just replace var. |
const CHARACTER_LIMIT = 255; const posts = [ "#DeepLearning transforms everything from self-driving cars to language translations. AND it's our new Nanodegree!", "Within your first week of the VR Developer Nanodegree Program, you'll make your own virtual reality app", "I just finished @udacity's Front-End Web Developer Nanodegree. Check it out!" ]; // prints posts to the console function displayPosts() { for (let i = 0; i < posts.length; i++) { console.log(posts[i].slice(0, CHARACTER_LIMIT)); } } displayPosts();
Since let can be changed, it would be perfect for a for loop.
Definition: MDN web doc
Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them. They were called "template strings" in prior editions of the ES2015 specification.
Along with var being obsolete, now it’s the string concatenation operator (+) . The old way was:
const student = { name: 'Richard Kalehoff', guardian: 'Mr. Kalehoff' }; const teacher = { name: 'Mrs. Wilson', room: 'N231' } let note = teacher.name + ',\n\n' + 'Please excuse ' + student.name + '.\n' + 'He is recovering from the flu.\n\n' + 'Thank you,\n' + student.guardian;
Which would read:
Mrs. Wilson,
Please excuse Richard Kalehoff. He is recovering from the flu.
Thank you, Mr. Kalehoff
The problem was that it gets a bit messy and confusing. So here they want to introduce template literals (previously referred to as template strings).
The new way doesn’t use single or double quotes for strings. Instead the whole thing is wrapped in the backticks and the placeholders would be wrapped in ${placeholders}.
example:
let message = `${student.name} please see ${teacher.name} in ${teacher.room} to pick up your report card.`;
Which would read:
Richard Kalehoff please see Mrs. Wilson in N231 to pick up your report card.
The new way shines when it comes to multi-line.
For example:
let note = `${teacher.name}, Please excuse ${student.name}, He is recovering from the flu. Thank you, ${student.guardian}`;
The template literals preserve newlines as part of the string.
Note
|
Embedded expressions inside template literals can do more than just reference variables. You can perform operations, call functions and use loops inside embedded expressions. |
Using what we learned about Template Literals, we edit the old way to the new way. This lesson did really prove that the new way is definitely better. Don’t forget the back ticks.
Here’s the finished:
const cardHTML = `<div class="card"> <h3 class="name"> ${animal.name} </h3> <img src="${animal.name}.jpg" alt="${animal.name}" class="picture"> <div class="description"> <p class="fact">${animal.fact} </p> <ul class="details"> <li><span class="bold">Scientific Name</span>: ${animal.scientificName} </li> <li><span class="bold">Average Lifespan</span>: ${animal.lifespan} </li> <li><span class="bold">Average Speed</span>: ${animal.speed} </li> <li><span class="bold">Diet</span>: ${animal.diet} </li> </ul> <p class="brief">${animal.summary}</p> </div> </div>;`
Definition: Destructuring Assignment
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
Important
|
There are different rules to destructuring when it comes to arrays and objects. |
Here’s the old way of destructuring an array:
const point = [10, 25, -34]; const x = point[0]; const y = point[1]; const z = point[2]; console.log(x, y, z);
And here’s the new way to destrucure an array:
let positions = ['Gabrielle', 'Jarrod', 'Kate', 'Fernando', 'Mike', 'Walter']; let [first, second, third] = positions;
If you wanted to know what would run if you typed in console.log(second), you would get Jarrod because he is in the second slot.
The old way for destructuring an object was like this:
const gemstone = { type: 'quartz', color: 'rose', karat: 21.29 }; const type = gemstone.type; const color = gemstone.color; const karat = gemstone.karat; console.log(type, color, karat);
The new way for dstructuring an object should be written like this:
const gemstone = { type: 'quartz', what: false, color: 'rose', else: 'cheeseburger', karat: 21.29 }; const {type, color, karat} = gemstone; console.log(type, color, karat);
Arrays destructuring went by position, but objects, you just use their property name.
Note
|
When you destructure an object and store a function into a variable, it no longer has access to this It will try and use the global. |
Now what if we wanted to give the destructured object a different variable and not what was in the object?
In that case, we can set it up using :.
const {type: newNAME1, color: newNAME2, karat: newNAME3} = gemstone
const circle = { radius: 10, color: ‘orange’, getArea: function() { return Math.PI * this.radius * this.radius; }, getCircumference: function() { return 2 * Math.PI * this.radius; } }; let {radius, getArea, getCircumference} = circle;
If we tried to do a console.log(getArea), we would get a NaN because when we destructured the object circle, it no longer has access to what this was and would try and retrieve from global instead.
so inside the function, this.radius, the call was trying to look for a radius variable from global and not inside the circle object.
The best way to regain access with the getArea function using this to listen to its mommy circle object, we can use bind, apply, and call.
To use call we put in getArea.call(). Inside the () we should refer to the original object with the function. So together it would look:
console.log(getArea.call(circle))
Note
|
I actually made a very in depth section on bind, apply, and call. Click to see it on Chapter 7: binding with call, apply, and bind. |
In here is a little quiz to see if we understand destructuring arrays.
Here are the changes when we only want the colors from the original array as a variable.
const things = ['red', 'basketball', 'paperclip', 'green', 'computer', 'earth', 'udacity', 'blue', 'dogs']; const [one, , ,two, , , ,three] = things;
When it comes to objects, sometimes it can be repetitive. The old way with objects initialization we used to do it this way:
let type = 'quartz'; let color = 'rose'; let carat = 21.29; const gemstone = { type: type, color: color, carat: carat }; console.log(gemstone);
The unecessary part is having to put type: type, color: color, and carat: carat. It’s redundant and unecessary now that ES6 figured out a way to simplify this. Now we can remove duplicate variables names from object properties if the properties hve the same name as the variable being assigned to them.
new way:
let type = 'quartz'; let color = 'rose'; let carat = 21.29; let gemstone = { type, color, carat };
There is also a shorthand way to add methods to objects.
The old way of adding a method in an object was:
const gemstone = { type, color, carat, calculateWorth: function() { } }
The ES6 way is:
let gemstone = { type, color, carat, calculateWorth() { } }
Basically function keyword was unecessary and was removed.
First half summary:
-
let and const are the new ways of declaring variables. let can be reassigned, but cannot be redeclared. const cannot be reassigned nor redeclared.
-
template literals replaces the concatenation operator. instead of 'string' + PH + 'string' + '\n' + PH + 'string' , you can now envelope everything with a back tick, placeholders are just encased in ${placeholder}, and strings are just left alone. Also, any new line is preserved as part of the string. example:
let message = ` ${placeholder} string string string string `
-
Destructuring arrays and objects makes it a whole lot more simpler to unpack values. Instead of creating a new variable for each line, now we can mash them all together and only the placement is important. However, if we need to skip one, we use an empty comma.
const things = ['red', 'basketball', 'paperclip', 'green', 'computer', 'earth', 'udacity', 'blue', 'dogs']; const [one, , ,two, , , ,three] = things;
-
shorthand ways of initilizing an object. If the object was going to have the same property as the name, we can now just use it once. example of the old way: const gemstone = {type:type, color:color} Now we can just make it like this: let gemstone = {type, color}
The second half of chapter 6 is is going to consist of:
-
iteration
-
for…of loop
-
rest parameter
-
spread operator
They recommend the best way to understand iteration is to look at a normal for loop.
for (let i = 0; i < 10; i++) { console.log(digits[i]; }
-
In the for loop we give it an i variable. It can be any variable, but i is typical since it stands for iteration.
An iterator keeps track of your place in the loop. When it comes to looping an array, the iterator works like an index and lets you access each item in the array one after another. The process of getting the next item one after the other is iteration.
-
Iterable protocol - allows javaScript objects to define or customize their iteration behavior.
Which is a new iterable interface that allows us to customize how objects are iterated. ie: changes how they’re looped.
More information on Iterable protocol will be discussed when they talk about symbols.
-
for…of loop - a loop that iterates over iterable objects - This loops exclusively over iterable objects. So what does an iterable object mean?
They want us to replace the old for loop with the new for…of loop. More will be discussed in the lesson.
The for…of loop was added in ES6. It combines the strengths of its siblings: for loop and the for…in loop to loop over any type of data that is iterable. Which means it has to follow the rules of iteration protocols. The data types it can loop are strings, arrays, maps, and sets. By default, it doesn’t iterate object data types.
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i = 0; i < digits.length; i++) { console.log(digits[i]); }
Which prints out 0 - 9 one by one.
The biggest downside of a for loop is having to keep track of the counter and exit condition. the counter is the first part i = 0. the exit condition is digits.length. This for loop is great for arrays, but other data types won’t work that well.
the drawbacks of the for loop was improved with the for…in loop. It eliminates the counting logic and exit condition but outputs the same as the for loop.
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const index in digits) { console.log(digits[index]); }
You still have to use an index to access the values of the array. Also, the biggest issue with for…in loops is that you get in trouble when you need to add an extra method to an array or another object.
Since for…in loops loop over all enumerable properties, this means if you add any additional properties to the array’s prototype, then those properties will also appear in the loop.
Array.prototype.decimalfy = function() { for (let i = 0; i < this.length; i++) { this[i] = this[i].toFixed(2); } }; const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const index in digits) { console.log(digits[index]); }
will print out…
0 1 2 3 4 5 6 7 8 9 function() { for (let i = 0; i < this.length; i++) { this[i] = this[i].toFixed(2); } }
The for…of loop is used to loop over any type of data that is iterable.
You would write a for…of loop almost exactly like you would write a for…in loop, except you swap out in with of and remove index.
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let digit of digits) { console.log(digit); }
Note
|
For good practice, when giving the name of the arrays, use plural, but when giving it a new name in the for…of loop, give it a singular name. When you do call it, you call the singular version. |
The quiz wants us to write a for…of loop that:
-
loops through each day in the days array
-
capitalizes the first letter of the day
-
and prints the day out to the console
using this
const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
From what we’ve learned, here’s how to write a for…of looop to print out each entry in the array.
for (let day of days) { console.log(day); }
Now how do we capitalize the first letter of the day?
first we need to store the new information in the variable. Next we need to select that first letter using charAt(index). Then we use that information for the toUpperCase.
day = day.charAt(0).toUpperCase()
Then we need to glue the rest with substr(start, end). since second part is left out, it’ll be just be the rest.
day = day.charAt(0).toUpperCase() + day.substr(1)
Here’s how it all came togteher:
for (let day of days) { day = day.charAt(0).toUpperCase() + day.substr(1); console.log(day); }
A spread operator is (…). The spread operator gives us the ability to expand, or spread iterable object into multiple elements.
example 1:
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"]; console.log(...books); prints: Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities
example 2:
const primes = new Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 29]); console.log(...primes); Prints: 2 3 5 7 11 13 17 19 23 29
The first example would work regardless of the spread operator, but the example is where the spread operator is useful. In example 2 both of the array and set have been expanded into their individual elements.
Here’s more information on sets. Sets is a new built-in object and was recently added in ES6.
Another example of the spread operator being useful is combining arrays.
The old way of combining arrays, we had to use concat() method.
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = fruits.concat(vegetables); console.log(produce); Prints: ["apples", "bananas", "pears", "corn", "potatoes", "carrots"]
Since ES6 is all about writing less, there’s a better way to combine arrays.
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = [fruits, vegetables]; console.log(produce); prints out: [ [ 'apples', 'bananas', 'pears' ], [ 'corn', 'potatoes', 'carrots' ] ]
but if we use the spread operator for each of the arrays…
const produce = [...fruits, ...vegetables]; console.log(produce); prints out: [ 'apples', 'bananas', 'pears', 'corn', 'potatoes', 'carrots' ]
So the spread operator spreads an array into multiple elements, so the opposite of that would be a way to bundle multiple elements into an array.
Introducing the rest parameter. It’s written the same way as the spread operator with the three consecutive dots (…).
The rest parameter allows us to represent an indefinite number of elements as an array.
When we use the …rest parameter in an array destructuring example below:
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"]; const [total, subtotal, tax, ...items] = order; console.log(total, subtotal, tax, items); prints: 20.17 18.67 1.5 ["cheese", "eggs", "milk", "bread"]
Basically when you use (…) in this case, it created a new array with the rest of the items in the order array.
Here’s another example of the rest parameter. This one is with the for…of loop.
printPackageContents('cheese', 'eggs', 'milk', 'bread'); function printPackageContents(...items) { for (const item of items) { console.log(item); } }
The …rest parameter is also great when it comes to variadic functions.
Variadic functions are functions that take an indefinite number of arguments. such as the sum() function. example: sum(1, 3, 20, 30,);
The old way of handling a sum function, we had to write it like this:
function sum() { let total = 0; for(const argument of arguments) { total += argument; } return total; }
It would work, but it had a few issues on its readability.
1. It has no parameters even though what we learned about variadic functions, the sum() should be able to hold an indefinite amount of arguments.
2. It’s difficult to understand what was going on.
Here’s the sum function with the rest parameter.
function sum(...nums) { let total = 0; for(const num of nums) { total += num; } return total; }
The rule is that we have to try and get the average when these numbers get entered
average(2, 6) should return 4 average(2, 3, 3, 5, 7, 10) should return 5 average(7, 1432, 12, 13, 100) should return 312.8 average() should return 0
What’s already there is an average function. Now we will have to put what we learned for it to output an average.
I had to go back to elementary school to figure out how to even get an average in the first place.
Add the numbers together and then divide how many there are ex: 6 + 11 + 7 = 24 24 / 3 = 8 so 8 is the average.
Step 1: The first step is a way to turn it into an array with the rest parameter.
function average(...nums) { }
Step 2: create a variable as a starting point. Since it will be changed, might as well just use let. One for the total numbers and one for the average.
let total = 0; let avg = 0;
Step 3: We would need to use a for…of loop to iterate what’s in the array.
for (const num of nums) { }
Step 4: Now we need to do something with that information.
I want to add each of the numbers and store it into total. With that total information, I want to divde the length of nums that the user will input. It will look like the math: (x + y) / z and store that into the avg variable.
avg = (total += num) / nums.length;
Step 5: Now we can just return the information from avg. return avg outside of that for…of loop.
Here’s how they all looked together:
function average(...nums) { let total = 0; let avg = 0; for (const num of nums) { avg = (total += num) / nums.length; } return avg; }