In this section, we present the most important new language elements introduced to JavaScript by ECMAScript 2015+ (that is, 2015+16+17+18+19+20+...).
ES5 did not allow declaring variables the scope of which is a block
delimited by a pair of curly braces, {
and
}
, or defined by a for
loop. Rather,
all variables declared with var
, even if declared
within a block, have either a function scope or the global scope. The new
feature of block-scope variable declarations with
let
and const
allows declaring local
variables with a finer-grained scope, which helps avoiding unintended
variable duplications and writing more modular code.
There is only one meaning difference between let
and const
. Variables declared with
const
are frozen or
immutable, and in this sense
constant, while let
variables are
not. It is preferable to use const
for all variables
that are not supposed to change their values. Otherwise, or if this is not
clear, one should declare the variable with let
if it
is a block-scoped variable, or with var
if it is a
global or function-scoped variable.
Compared to classical JS functions, arrow functions (with =>)
provide a more concise function expression syntax, see Ex. 1, and allow
using JavaScript's this
variable from the function's
outer environment (its closure) in their function
body, see Ex. 2.
Example 2.1. Code Example 1
let evens = [0,2,4,6,8];
let odds = evens.map( v => v+1); // [1,3,5,7,9]
// instead of evens.map( function (v) {return v+1;})
Example 2.2. Code Example 2
this.nums = [1,3,5,8,10,12,15,17];
this.fives = [];
this.nums.forEach( v => {if (v % 5 === 0) this.fives.push(v);});
// instead of this.nums.forEach(
// function (v) {if (v % 5 === 0) this.fives.push(v);}, this)
Iterable objects include strings, arrays, array-like objects (e.g.,
the built-in arguments
object or instances of
HTMLCollections
and NodeList
), and
instances of the datatype objects TypedArray
,
Map
, and Set
, as well as
user-defined iterables. For instance,
const divElems = document.getElementsByTagName("div"); // an HTMLCollection is iterable for (const dEl of divElems) { console.log( dEl.id); }
A for-of loop is often more handy than a
for loop whenever a counter variable is not needed.
As opposed to a forEach
loop, a
for-of loop allows iterating over
HTMLCollections
and can be abandoned with
break
.
... are enclosed by backtick characters (like `... `) instead of double or single quotes and allow a concise syntax for (possibly multi-line) string values resulting from a combination of fixed text parts and variables/expressions. For instance,
const classValues = "card important"; const name = "Joker"; const htmlTemplate = `<div class="${classValues}"> <p>Hello ${name}!</p> </div>`
...allows spreading (1) the elements of an iterable collection in places where arguments for function calls or array elements are expected, or (2) the slots of a JS object in places where name-value pairs are expected. For instance,
let nums = [3,4,5], otherNums = [1, 2, ...nums]; // [1,2,3,4,5] // cloning an array let numsClone = [...nums]; // cloning an object let book = {title:"JavaScript: The Good Parts"}; let bookClone = {...book};
...allow a concise syntax for assigning the property values of a JS object or the elements of a JS array to corresponding variables. For instance,
var point1 = [10,5]; var [x,y] = point1; // a destructuring assignment console.log(`x = ${x} | y = ${y}`); // x = 10 | y = 5 var person1 = {firstName:"James", lastName:"Bond"}; var {first, last} = person1; console.log(`first:${first} | last:${last}`); // Output: first:James | last:Bond
Example 2.3. Dealing with multiple return values of a function
function getRectangle () {
return {width: 50, height: 20};
}
const {a, b} = getRectangle();
drawRectangle( a, b);
Example 2.4. Swapping two variables
var a = 1, b = 2;
[a,b] = [b,a];
console.log(`a = ${a} | b = ${b}`);
// Output: a = 2 | b = 1
Example 2.5. Simplifying functions with parameter records
A function parameter record allows using named arguments in function calls instead of argument lists like so:
function displayName( paramRec) { alert( paramRec.first + " " + paramRec.last); }; displayName({first:"James", last:"Bond"});
Using Destructuring, the parameter record fields are assigned to ordinary function parameters, simplifying the function's code:
function displayName({first, last}) {
alert( first + " " + last);
}
displayName({first:"James", last:"Bond"});