Part 1
What is ES?
ECMAScript is a standardized version of JavaScript with the goal of unifying the language’s specifications and features. As all major browsers and JavaScript-runtimes follow this specification, the term ECMAScript is interchangeable with the term JavaScript.
The most recent standardized version is called ECMAScript 6 (ES6), released in 2015. This new version of the language adds some powerful features including:
- Arrow functions
- Classes
- Modules
- Promises
- Generators
- let and
const
1. Explore Differences Between the var and let Keywords
- Why was
let
added as a keyword?- A variable with the same name can only be declared once using
let
- A variable with the same name can only be declared once using
// var
var camper = 'James';
var camper = 'David';
console.log(camper);
// logs 'David'
//let
let camper = 'James';
let camper = 'David'; // throws an error
-
Compare Scopes of the var and let Keywords
-
When you declare a variable with the
var
keyword, it is declared globally, or locally if declared inside a function. -
The
let
keyword behaves similarly, but with some extra features. When you declare a variable with thelet
keyword inside a block, statement, or expression, its scope is limited to that block, statement, or expression.
-
var numArray = [];
for (var i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3
is similar to
var numArray = [];
var i;
for (i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3
however, this can cause issues
var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 3
let
can fix it!
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"
2. What is use strict
?
The “use strict” enables Strict Mode, which catches common coding mistakes and “unsafe” actions.
- Example 1
"use strict";
x = 3.14; // throws an error because x is not declared
- Example 2
let catName;
let quote;
function catTalk() {
"use strict";
catName = "Oliver";
quote = catName + " says Meow!";
}
catTalk();
3. Declare a Read-Only Variable with the const
Keyword
const
has all the awesome features that let has, with the added bonus that variables declared usingconst
are read-only.- They are a constant value, which means that once a variable is assigned with
const
, it cannot be reassigned - You should always name variables you don’t want to reassign using the const keyword
function printManyTimes(str) {
"use strict";
// Only change code below this line
const END_WORDS = " is cool!";
const SENTENCE = str + END_WORDS;
for (let i = 0; i < str.length; i+=2) {
console.log(SENTENCE);
}
// Only change code above this line
}
printManyTimes("freeCodeCamp");
4. Mutate an Array Declared with const
- Objects (including arrays and functions) assigned to a variable using const are still mutable. Using the const declaration only prevents reassignment of the variable identifier.
"use strict";
const s = [5, 6, 7];
s = [1, 2, 3]; // throws error, trying to assign a const
s[2] = 45; // works just as it would with an array declared with var or let
console.log(s); // returns [5, 6, 45]
5. Prevent Object Mutation
- To ensure your data doesn’t change, JavaScript provides a function Object.freeze to prevent data mutation ❄️
- Once the object is frozen, you can no longer add, update, or delete properties from it. Any attempt at changing the object will be rejected without an error.
function freezeObj() {
'use strict';
const MATH_CONSTANTS = {
PI: 3.14
};
// Only change code below this line
Object.freeze(MATH_CONSTANTS);
// Only change code above this line
try {
MATH_CONSTANTS.PI = 99;
} catch(ex) {
console.log(ex);
}
return MATH_CONSTANTS.PI;
}
const PI = freezeObj();
5. Use Arrow Functions to Write Concise Anonymous Functions ➡️
-
In JavaScript, we often don’t need to name our functions, especially when passing a function as an argument to another function.
-
Instead, we create
inline functions
. We don’t need to name these functions because we do not reuse them anywhere else. -
Example 1
const myFunc = function() {
const myVar = "value";
return myVar;
}
// ES6 provides us with the syntactic sugar to not have to write anonymous functions this way. Instead, you can use arrow function syntax:
const myFunc = () => "value";
- Example 2
const magic = () => {
"use strict";
return new Date();
};
6. Write Arrow Functions with Parameters ➡️
- Just like a regular function, you can pass arguments into an arrow function
- If an arrow function has a single argument, the parentheses enclosing the argument may be omitted
// doubles input value and returns it
const doubler = (item) => item * 2;
// or
// the same function, without the argument parentheses
const doubler = item => item * 2;
- It is possible to pass more than one argument into an arrow function
// multiplies the first input value by the second and returns it
const multiplier = (item, multi) => item * multi;
- Example: write the myConcat function which appends contents of arr2 to arr1 so that the function uses arrow function syntax
const myConcat = (arr1, arr2) => {
"use strict";
arr1.concat(arr2)
}
console.log(myConcat([1, 2], [3, 4, 5]));
7. Set Default Parameters for Your Functions
- In order to help us create more flexible functions, ES6 introduces default parameters for functions
const greeting = (name = "Anonymous") => "Hello " + name;
console.log(greeting("John")); // Hello John
console.log(greeting()); // Hello Anonymous
// Create an increment function by adding default parameters so that it will add 1 to number if value is not specified
const increment = (number, value=1) => number + value;
8. Use the Rest Parameter ...args
with Function Parameters
- In order to help us create more flexible functions, ES6 introduces the rest parameter for function parameters.
- With the rest parameter, you can create functions that take a variable number of arguments.
- These arguments are stored in an array that can be accessed later from inside the function.
- The rest parameter eliminates the need to check the args array and allows us to apply map(), filter() and reduce() on the parameters array
- Example
const sum = (x, y, z) => {
const args = [x, y, z];
return args.reduce((a, b) => a + b, 0);
}
// can be rewritten as
const sum(...args){
return args.reduce((a,b) => a+b,0)
}
9. Use the Spread Operator to Evaluate Arrays In-Place
- The spread operator allows us to expand arrays and other expressions in places where multiple parameters or elements are expected
// ES5: We had to use Math.max.apply(null, arr) because Math.max(arr) returns NaN. Math.max() expects comma-separated arguments, but not an array.
var arr = [6, 89, 3, 45];
var maximus = Math.max.apply(null, arr); // returns 89
// ES6: ...arr returns an unpacked array. In other words, it spreads the array.
const arr = [6, 89, 3, 45];
const maximus = Math.max(...arr); // returns 89
- The spread operator only works in-place, like in an argument to a function or in an array literal. The following code will not work:
const spreaded = ...arr; // will throw a syntax error
- Example
const arr1 = ['JAN', 'FEB', 'MAR', 'APR', 'MAY'];
let arr2;
arr2 = []; // Change this line
console.log(arr2);
// rewritten as
(function() {
"use strict";
arr2 = [...arr1]; // change this line
})();
10. Use Destructuring Assignment to Extract Values from Objects
- Destructuring assignment is special syntax introduced in ES6, for neatly assigning values taken directly from an object
- You can extract as many or few values from the object as you want
- Example 1
//ES5
const user = { name: 'John Doe', age: 34 };
const name = user.name; // name = 'John Doe'
const age = user.age; // age = 34
//ES6
const { name, age } = user;
// name = 'John Doe', age = 34
// Here, the name and age variables will be created and assigned the values of their respective values from the user object. You can see how much cleaner this is.
- Example 2
const HIGH_TEMPERATURES = {
yesterday: 75,
today: 77,
tomorrow: 80
};
// Only change code below this line
const {today, tomorrow} = HIGH_TEMPERATURES;
// Only change code above this line
11. Use Destructuring Assignment to Assign Variables from Objects
- Destructuring allows you to assign a new variable name when extracting values. You can do this by putting the new name after a colon when assigning the value.
- Example 1
const user = { name: 'John Doe', age: 34 };
//ES6
const { name: userName, age: userAge } = user;
// userName = 'John Doe', userAge = 34
12. Use Destructuring Assignment to Assign Variables from Nested Objects
const user = {
johnDoe: {
age: 34,
email: 'johnDoe@freeCodeCamp.com'
}
};
// ES6
// extract the values of object properties and assign them to variables with the same name
const { johnDoe: { age, email }} = user;
// assign an object properties' values to variables with different names
const { johnDoe: { age: userAge, email: userEmail }} = user;
- Example 2
const LOCAL_FORECAST = {
yesterday: { low: 61, high: 75 },
today: { low: 64, high: 77 },
tomorrow: { low: 68, high: 80 }
};
const {today:{low:lowToday, high:highToday}} = LOCAL_FORECAST
13. Use Destructuring Assignment to Assign Variables from Arrays
- One key difference between the spread operator and array destructuring is that:
- the spread operator unpacks all contents of an array into a comma-separated list. Consequently, you cannot pick or choose which elements you want to assign to variables.
// Destructuring an array lets us do exactly that:
const [a, b] = [1, 2, 3, 4, 5, 6];
console.log(a, b); // 1, 2
// We can also access the value at any index in an array with destructuring by using commas to reach the desired index
const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
console.log(a, b, c); // 1, 2, 5
- Exmple 2
let a = 8, b = 6;
// Use destructuring assignment to swap the values of a and b so that a receives the value stored in b, and b receives the value stored in a.
// Only change code below this line
[a,b ]=[b,a];
// Do not try to re-declare a or b while destructuring as they are already declared in the first let statement.
14. Use Destructuring Assignment with the Rest Parameter to Reassign Array Elements
- In some situations involving array destructuring, we might want to collect the rest of the elements into a separate array
- The result is similar to Array.prototype.slice(), as shown below
- The rest element only works correctly as the last variable in the list. As in, you cannot use the rest parameter to catch a subarray that leaves out the last element of the original array.
- Example 1
const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
console.log(a, b); // 1, 2
console.log(arr); // [3, 4, 5, 7]
- Example 2
const source = [1,2,3,4,5,6,7,8,9,10];
function removeFirstTwo(list) {
"use strict";
// Only change code below this line
const [a, b,...arr] = list;
// Only change code above this line
return arr;
}
const arr = removeFirstTwo(source);
15. Use Destructuring Assignment to Pass an Object as a Function’s Parameters
- In some cases, you can destructure the object in a function argument itself
- This removes some extra lines and makes our code look neat
- This has the added benefit of not having to manipulate an entire object in a function — only the fields that are needed are copied inside the function
- Example 1
const profileUpdate = (profileData) => {
const { name, age, nationality, location } = profileData;
// do something with these variables
}
//ES6
const profileUpdate = ({ name, age, nationality, location }) => {
/* do something with these fields */
}
//
- Example 2
const stats = {
max: 56.78,
standard_deviation: 4.34,
median: 34.54,
mode: 23.87,
min: -0.75,
average: 35.85
};
// Only change code below this line
const half = (stats) => (stats.max + stats.min) / 2.0;
// Only change code above this line
//ES6
const stats = {
max: 56.78,
standard_deviation: 4.34,
median: 34.54,
mode: 23.87,
min: -0.75,
average: 35.85
};
// Only change code below this line
const half = ({ max, min }) => (max + min) / 2.0;
// Only change code above this line