Java Guide

Introduction to ES6 [1][0]

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.

JavaScript is an evolving programming language.
As features are added and revisions are made, new versions of the language are released for use by developers.

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

Not all browsers support ES6 features.

Differences Between the var and let Keywords [1][1]

One of the biggest problems with declaring variables with the var keyword is that you can overwrite variable declarations without an error.


var camper = 'James'; var camper = 'David'; console.log(camper); // logs 'David'

As you can see in the code above, the camper variable is originally declared as James and then overridden to be David.
In a small application, you might not run into this type of problem, but when your code becomes larger,
you might accidentally overwrite a variable that you did not intend to overwrite.

Because this behavior does not throw an error, searching and fixing bugs becomes more difficult.
A new keyword called let was introduced in ES6 to solve this potential issue with the var keyword.

If you were to replace var with let in the variable declarations of the code above, the result would be an error.


let camper = 'James'; let camper = 'David'; // throws an error

This error can be seen in the console of your browser.
So unlike var, when using let, a variable with the same name can only be declared once.

Note the "use strict". This enables Strict Mode, which catches common coding mistakes and "unsafe" actions.


"use strict"; x = 3.14; // throws an error because x is not declared

Compare Scopes of the var and let Keywords [1][2]

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 the let 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

With the var keyword, i is declared globally. So when i++ is executed, it updates the global variable.

This code 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

This behavior will cause problems if you were to create a function and store it for later use inside a for loop that uses the i variable.
This is because the stored function will always refer to the value of the updated global i variable.

var printNumTwo; for (var i = 0; i < 3; i++) { if(i === 2){ printNumTwo = function() { return i; }; } } console.log(printNumTwo()); // returns 3

As you can see, printNumTwo() prints 3 and not 2. This is because the value assigned to i was updated
and the printNumTwo() returns the global i and not the value i had when the function was created in the for loop.

The let keyword does not follow this behavior:

'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"

i is not defined because it was not declared in the global scope.
It is only declared within the for loop statement. printNumTwo() returned the correct value
because three different i variables with unique values (0, 1, and 2) were created by the let keyword within the loop statement.

Declare a Read-Only Variable with the const Keyword [1][3]

let is not the only new way to declare variables. In ES6, you can also declare variables using the const keyword.
const has all the awesome features that let has, with the added bonus that variables declared using const are read-only.
They are a constant value, which means that once a variable is assigned with const, it cannot be reassigned.


"use strict"; const FAV_PET = "Cats"; FAV_PET = "Dogs"; // returns error

As you can see, trying to reassign a variable declared with const will throw an error.
You should always name variables you don't want to reassign using the const keyword.
This helps when you accidentally attempt to reassign a variable that is meant to stay constant.

A common practice when naming constants is to use all uppercase letters, with words separated by an underscore.

Mutate an Array Declared with const [1][4]

The const declaration has many use cases in modern JavaScript.
Some developers prefer to assign all their variables using const by default, unless they know they will need to reassign the value.
Only in that case, they use let.

However, it is important to understand that 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]

As you can see, you can mutate the object [5, 6, 7] itself and the variable S will still point to the altered array [5, 6, 45].
Like all arrays, the array elements in S are mutable, but because const was used,
you cannot use the variable identifier S to point to a different array using the assignment operator.

Prevent Object Mutation [1][5]

const declaration alone doesn't really protect your data from 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.


let obj = { name:"FreeCodeCamp", review:"Awesome" }; Object.freeze(obj); = "bad"; // will be ignored. Mutation not allowed obj.newProp = "Test"; // will be ignored. Mutation not allowed console.log(obj); // { name: "FreeCodeCamp", review:"Awesome"}

Use Arrow Functions to Write Concise Anonymous Functions [1][6]

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.

To achieve this, we often use the following syntax:


const MYFUNC = function() { const MYVAR = "value"; return MYVAR; }

ES6 provides us with the syntax to not have to write anonymous functions this way.
Instead, you can use arrow function syntax.


const MYFUNC = () => { const MYVAR = "value"; return MYVAR; }

When there is no function body, and only a return value, arrow function syntax allows you to omit the keyword return
as well as the brackets surrounding the code.

This helps simplify smaller functions into one-line statements.

const MYFUNC = () => "value"

This code will still return value by default.

Write Arrow Functions with Parameters [1][7]

Just like a normal function, you can pass arguments into arrow functions.


const DOUBLER = (item) => item * 2; // doubles input value and returns it

You can pass more than one argument into arrow functions as well.


const MYCONCAT = (arr1, arr2) => arr1.concat(arr2); console.log(MYCONCAT([1, 2], [3, 4, 5])); // Returns: " 1,2,3,4,5 "

Write Higher Order Arrow Functions [1][8]

Arrow functions work really well with higher order functions, such as map(), filter(), and reduce(),
that take other functions as arguments for processing collections of data.

Read the following code:

FBPosts.filter(function(post) { return post.thumbnail !== null && post.shares > 100 && post.likes > 500; })

This is written with filter() to at least make it somewhat readable.

Now compare it to the following code which uses arrow function syntax instead:

FBPosts.filter((post) => post.thumbnail !== null && post.shares > 100 && post.likes > 500)

This code is more succinct and accomplishes the same task with fewer lines of code.

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.


const REALNUMBERARRAY = [4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]; const SQUARELIST = (arr) => { "use strict"; const SQUAREDINTEGERS = arr.filter( (num) => num > 0 && num % 2 === 0).map( (num) => Math.pow(num,2)); return SQUAREDINTEGERS; }; const SQUAREDINTEGERS = SQUARELIST(REALNUMBERARRAY); console.log(SQUAREDINTEGERS); // Returns: " 16,1764,36 " as in 42, 422 and 62 (the only positive integers)

Set Default Parameters for Functions [1][9]

In order to help create more flexible functions, ES6 introduces default parameters for functions.


function greeting(name = "Anonymous") { return "Hello " + name; } console.log(greeting("John")); // Hello John console.log(greeting()); // Hello Anonymous

The default parameter kicks in when the argument is not specified (it is undefined).
As you can see in the example above, the parameter name will receive its default value "Anonymous" when you
do not provide a value for the parameter. You can add default values for as many parameters as you want.


const INCREMENT = (function() { "use strict"; return function INCREMENT(number, value = 1) { return number + value; }; })(); console.log(INCREMENT(5, 2)); // returns 7 console.log(INCREMENT(5)); // returns 6

Use the Rest Operator with Function Parameters [1][10]

In order to help create more flexible functions, ES6 introduces the rest operator " ... " for function parameters.
With the rest operator, 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.


function howMany(...args) { return "You have passed " + args.length + " arguments."; } console.log(howMany(0, 1, 2)); // You have passed 3 arguments console.log(howMany("string", null, [1, 2, 3], { })); // You have passed 4 arguments

The rest operator " ... " eliminates the need to check the args array and allows us to apply map(), filter() and reduce() on the parameters array.

const sum = (function() { "use strict"; return function sum(...args) { return args.reduce((a, b) => a + b, 0); }; })(); console.log(sum(1, 3, 5, 7, 9)); // returns 25

Use the Spread Operator to Evaluate Arrays In-Place [1][11]

The spread operator allows us to expand arrays and other expressions in places where multiple parameters or elements are expected.

The ES5 code below uses apply() to compute the maximum value in an array:

var arr = [6, 89, 3, 45]; var maximus = Math.max.apply(null, arr); // returns 89

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.

The spread operator makes this syntax much better to read and maintain.

const arr = [6, 89, 3, 45]; const maximus = Math.max(...arr); // returns 89 const ARR1 = ['JAN', 'FEB', 'MAR', 'APR', 'MAY']; let arr2; (function() { "use strict"; arr2 = [...ARR1]; })(); console.log(arr2); // will return JAN,FEB,MAR,APR,MAY

...arr returns an unpacked array. In other words, it spreads the array.

However, 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

Use Destructuring Assignment to Assign Variables from Objects [1][12]

Destructuring assignment is special syntax for neatly assigning values taken directly from an object to variables.

Consider the following ES5 code:

var voxel = {x: 3.6, y: 7.4, z: 6.54 }; var x = voxel.x; // x = 3.6 var y = voxel.y; // y = 7.4 var z = voxel.z; // z = 6.54

Here's the same assignment statement with ES6 destructuring syntax:

var voxel = {x: 3.6, y: 7.4, z: 6.54 }; const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54

If instead you want to store the values of voxel.x into a, voxel.y into b,and voxel.z into c, you have that freedom as well.

var voxel = {x: 3.6, y: 7.4, z: 6.54 }; const { x : a, y : b, z : c } = voxel // a = 3.6, b = 7.4, c = 6.54

You may read it as "get the field x and copy the value into a," and so on.

const AVG_TEMPERATURES = { today: 77.5, tomorrow: 79 }; function getTempOfTmrw(avgTemperatures) { "use strict"; const { tomorrow : tempOfTomorrow } = avgTemperatures; return tempOfTomorrow; } console.log(getTempOfTmrw(AVG_TEMPERATURES)); // returns 79

Memo to self
You are using directly the name of your tested object (AVG_TEMPERATURES) within your function, which makes it contingent.
You should put the name of your argument instead (avgTemperatures), so your function can be used
with several “temperature” objects that have a tomorrow value.

Use Destructuring Assignment to Assign Variables from Nested Objects [1][13]

Destructure nested objects into variables.

Consider the following code:

const A = { start: { x: 5, y: 6}, end: { x: 6, y: -9 } }; const { start : { x: startX, y: startY }} = A; console.log(startX, startY); // 5, 6

In the example above, the variable start is assigned the value of A.start, which is also an object.


const LOCAL_FORECAST = { today: { min: 72, max: 83 }, tomorrow: { min: 73.3, max: 84.6 } }; function getMaxOfTmrw(forecast) { "use strict"; const { tomorrow : { max : maxOfTomorrow}} = forecast; return maxOfTomorrow; } console.log(getMaxOfTmrw(LOCAL_FORECAST)); // returns max temp tomorrow : 84.6

Use Destructuring Assignment to Assign Variables from Arrays [1][14]

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

The variable a is assigned the first value of the array, and b is assigned the second value of the array.

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


let a = 8, b = 6; console.log(a); // returns 8 console.log(b); // returns 6 (() => { "use strict"; [a,b] = [b,a]; })(); console.log(a); // returns 6 console.log(b); // returns 8

Same (function) code

(() => { "use strict"; [a,b] = [b,a]; })();

Use Destructuring Assignment with the Rest Operator to Reassign Array Elements [1][15]

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:

const [a, b, ...arr] = [1, 2, 3, 4, 5, 7]; console.log(a, b); // 1, 2 console.log(arr); // [3, 4, 5, 7]

Variables a and b take the first and second values from the array. After that, because of rest operator's presence,
arr gets rest of the values in the form of an array.

The rest element only works correctly as the last variable in the list.
As in, you cannot use the rest operator to catch a subarray that leaves out last element of the original array.


const SOURCE = [1,2,3,4,5,6,7,8,9,10]; function removeFirstTwo(list) { "use strict"; const [,,...arr] = list; return arr; } const arr = removeFirstTwo(SOURCE); console.log(arr); // returns [3,4,5,6,7,8,9,10] console.log(SOURCE); // returns [1,2,3,4,5,6,7,8,9,10];

Use Destructuring Assignment to Pass an Object as a Function's Parameters [1][16]

In some cases, you can destructure the object in a function argument itself.

Consider the code below:

const profileUpdate = (profileData) => { const { name, age, nationality, location } = profileData; // do something with these variables }

This effectively destructures the object sent into the function.

This can also be done in-place:

const profileUpdate = ({ name, age, nationality, location }) => { /* do something with these fields */ }

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.


const STATS = { max: 56.78, standard_deviation: 4.34, median: 34.54, mode: 23.87, min: -0.75, average: 35.85 }; const half = (function() { "use strict"; return function half({max, min}) { return (max + min) / 2.0; // (56.78 + (-0.75))/2 }; })(); console.log(STATS); // returns object console.log(half(STATS)); // returns 28.015

Create Strings using Template Literals [1][17]

The template literal. This is a special type of string that makes creating complex strings easier.
Template literals allow you to create multi-line strings and to use string interpolation features to create strings.


const PERSON = { name: "Zodiac Hasbro", age: 56 }; // Template literal with multi-line and string interpolation const GREETING = `Hello, my name is ${}! I am ${PERSON.age} years old.`; console.log(GREETING); // returns 2 lines: // Hello, my name is Zodiac Hasbro! // I am 56 years old.

A lot of things happened there.

Firstly, the example uses backticks " ` ", not quotes " ' or " ", to wrap the string.

Secondly, notice that the string is multi-line : " ! ", both in the code and the output. This saves inserting \n within strings.

The ${variable} syntax used above is a placeholder. Basically, you won't have to use concatenation with the + operator anymore.
To add variables to strings, you just drop the variable in a template string and wrap it with ${ and }.
Similarly, you can include other expressions in your string literal, for example ${a + b}.

This new way of creating strings gives you more flexibility to create robust strings.


const RESULT = { success: ["max-length", "no-amd", "prefer-arrow-functions"], failure: ["no-var", "var-on-top", "linebreak"], skipped: ["id-blacklist", "no-dup-keys"] }; function makeList(arr) { "use strict"; const RESULTDISPLAYARRAY = (item) => `<li class="text-warning">${item}</li>`); return RESULTDISPLAYARRAY; } const RESULTDISPLAYARRAY = makeList(RESULT.failure); /* makeList(RESULT.failure) returns: [`<li class="text-warning">no-var</li>`, `<li class="text-warning">var-on-top</li>`, `<li class="text-warning">linebreak</li>`] */

Write Concise Object Literal Declarations Using Simple Fields [1][18]

ES6 adds some nice support for easily defining object literals.


const GETMOUSEPOSITION = (x, y) => ({ x: x, y: y });

GETMOUSEPOSITION is a simple function that returns an object containing two fields.

ES6 provides the syntax to eliminate the redundancy of having to write x: x.
You can simply write x once, and it will be converted to x: x (or something equivalent) under the hood.

Here is the same function from above rewritten to use this new syntax:

const getMousePosition = (x, y) => ({ x, y });
const CREATEPERSON = (name, age, gender) => { "use strict"; return { name: name, age: age, gender: gender }; }; console.log(CREATEPERSON("Zodiac Hasbro", 56, "male")); // returns a proper object


const CREATEPERSON = (name, age, gender) => ({ name, age, gender }); console.log(CREATEPERSON("Zodiac Hasbro", 56, "male")); // returns a proper object

Write Concise Declarative Functions with ES6 [1][19]

When defining functions within objects in ES5, we have to use the keyword function as follows:

const PERSON = { name: "Taylor", sayHello: function() { return `Hello! My name is ${}.`; } };

With ES6, You can remove the function keyword and colon altogether when defining functions in objects.

Here's an example of this syntax:

const PERSON = { name: "Taylor", sayHello() { return `Hello! My name is ${}.`; } };


const BICYCLE = { gear: 2, setGear: function(newGear) { "use strict"; this.gear = newGear; } }; BICYCLE.setGear(3); // set gear 3 console.log(BICYCLE.gear); // returns 3


const BICYCLE = { gear: 2, setGear(newGear) { "use strict"; this.gear = newGear; } }; BICYCLE.setGear(3); // set gear 3 console.log(BICYCLE.gear); // returns 3

Use class Syntax to Define a Constructor Function [1][20]

ES6 provides a new syntax to help create objects, using the keyword class.

This is to be noted, that the class syntax is just a syntax, and not a full-fledged class based implementation
of object oriented paradigm, unlike in languages like Java, or Python, or Ruby etc.

In ES5, we usually define a constructor function, and use the new keyword to instantiate an object.


var SpaceShuttle = function(targetPlanet){ this.targetPlanet = targetPlanet; } var zeus = new SpaceShuttle('Jupiter');

The class syntax simply replaces the constructor function creation:

class SpaceShuttle { constructor(targetPlanet){ this.targetPlanet = targetPlanet; } } const ZEUS = new SpaceShuttle('Jupiter');

Notice that the class keyword declares a new function, and a constructor was added,
which would be invoked when new is called - to create a new object.


function makeClass() { "use strict"; class VEGETABLE { constructor(name) { = name } } return VEGETABLE; } const VEGETABLE = makeClass(); const CARROT = new VEGETABLE('carrot'); console.log(; // returns 'carrot'

Use getters and setters to Control Access to an Object [1][21]

You can obtain values from an object, and set a value of a property within an object.

These are classically called getters and setters.

Getter functions are meant to simply return (get) the value of an object's private variable
to the user without the user directly accessing the private variable.

Setter functions are meant to modify (set) the value of an object's private variable
based on the value passed into the setter function. This change could involve calculations, or even overwriting the previous value completely.


class Book { constructor(author) { this._author = author; } // getter get writer(){ return this._author; } // setter set writer(updatedAuthor){ this._author = updatedAuthor; } } const LOL = new Book('anonymous'); console.log(LOL.writer); // anonymous LOL.writer = 'wut'; console.log(LOL.writer); // wut

Notice the syntax used to invoke the getter and setter - as if they are not even functions.
Getters and setters are important, because they hide internal implementation details.


function makeClass() { "use strict"; class THERMOSTAT { constructor (newTemp){ this._newTemp = 5/9 *(newTemp -32); // Convert (method) Fahrenheit to Celsius } // getter get temperature(){ return this._newTemp; } // setter set temperature(THERMOS){ this._newTemp = THERMOS; } } return THERMOSTAT; // return Output } const THERMOSTAT = makeClass(); // input for Class to convert F to C const THERMOS = new THERMOSTAT(77); // input in (77) degrees Fahrenheit let temp = THERMOS.temperature; // results output in degrees Celsius console.log(temp); // Returns 25

Understand the Differences Between import and require [1][22]

In the past, the function require() would be used to import the functions and code in external files and modules.
While handy, this presents a problem:
some files and modules are rather large, and you may only need certain code from those external resources.

ES6 gives us a very handy tool known as import.
With it, we can choose which parts of a module or file to load into a given file, saving time and memory.

Consider the following example.
Imagine that math_array_functions has about 20 functions, but you only need one, countItems, in your current file.
The old require() approach would force you to bring in all 20 functions.
With this new import syntax, you can bring in just the desired function, like so:
import { countItems } from "math_array_functions";

A description of the above code:

import { function } from "file_path_goes_here"; // We can also import variables the same way!

There are a few ways to write an import statement, but the above is a very common use-case.

The whitespace surrounding the function inside the curly braces is a best practice - it makes it easier to read the import statement.

These features handle non-browser features. import, and the statements we introduce in the rest of these lessons,
won't work on a browser directly. However, we can use various tools to create code out of this to make it work in browser.

In most cases, the file path requires a ./ before it; otherwise, node will look in the node_modules directory first trying to load it as a dependency.


import { capitalizeString } from "string_functions" "use strict"; console.log(capitalizeString("hello!")); // output: "HELLO!"

Use export to Reuse a Code Block [1][23]

About import and how it can be leveraged to import small amounts of code from large files.
In order for this to work, though, we must utilize one of the statements that goes with import, known as export.
When we want some code - a function, or a variable - to be usable in another file, we must export it
in order to import it into another file. Like import, export is a non-browser feature.

The following is what we refer to as a named export.
With this, we can import any code we exported into another file with the import syntax.


const CAPITALIZESTRING = (string) => { return string.charAt(0).toUpperCase() + string.slice(1); } export { CAPITALIZESTRING } //How to export functions. export const FOO = "bar"; //How to export variables.

Alternatively, if you would like to compact all your export statements into one line, you can take this approach:

const CAPITALIZESTRING = (string) => { return string.charAt(0).toUpperCase() + string.slice(1); } const FOO = "bar"; export { CAPITALIZESTRING, FOO }

Either approach is perfectly acceptable.


"use strict"; export const FOO = "bar"; export const BAR = "foo"; // SAME AS "use strict"; const FOO = "bar"; const BAR = "foo"; export { FOO, BAR }

Use * to Import Everything from a File [1][24]

Suppose you have a file that you wish to import all of its contents into the current file. This can be done with the import * syntax.

Here's an example where the contents of a file named "math_functions" are imported into a file in the same directory.

import * as myMathModule from "math_functions"; myMathModule.add(2,3); myMathModule.subtract(5,3);


import * as object_with_name_of_your_choice from "file_path_goes_here" object_with_name_of_your_choice.imported_function

You may use any name following the import * as portion of the statement.
In order to utilize this method, it requires an object that receives the imported values.
From here, you will use the dot notation to call your imported values.

Create an Export Fallback with export default [1][25]

There is another export syntax you need to know, known as export default.
Usually you will use this syntax if only one value is being exported from a file.
It is also used to create a fallback value for a file or module.


export default function add(x,y) { return x + y; }

Since export default is used to declare a fallback value for a module or file,
you can only have one value be a default export in each module or file.
Additionally, you cannot use export default with var, let, or const

Import a Default Export [1][26]

It is important to note that, to import a default export, you need to use a different import syntax.
In the following example, we have a function, add, that is the default export of a file, "math_functions".


import add from "math_functions"; add(5,4); //Will return 9

The syntax differs in one key place - the imported value, add, is not surrounded by curly braces, " { } ".
Unlike exported values, the primary method of importing a default export is to simply write the value's name after import.