ECMAScript 6 features

ECMAScript 6, otherwise called ECMAScript 2015, is the most recent form of the ECMAScript standard. ES6 is an important upgrade to the language, and the first update to language since the release of ES5.1 in June 2011

A few of the new features of ES6 are:

  • Arrow functions
  • Classes
  • Enhanced object literals
  • Destructuring assignment
  • Extended parameter handling
  • Generator
  • Modules
  • Proxy

We will look at all these functions in the upcoming sections.

Arrow functions

Arrow functions are also known as fat arrow functions. It is a function and is similar to what we use in C#, Java, and Coffee Script. Statements and expression bodies are supported by arrows. The lexical of arrows is similar to its surrounding code. This is not the case in functions.

As the name suggests, arrow functions use a shorter syntax, an arrow (=>), for definition and in syntax.

For example, look at the following example:

// An empty arrow function returns undefined
let empty =()=>{};

(()=>"pine")()// returns "pine"

var simple = a => a >20?20: a;
simple(20);// 20
simple(10);// 10

let max =(a, b)=> a > b ?a : b;

// Easy array filtering, mapping, ...

varsampleArray=[7,4,1,0,3,5,11];
var sum =sampleArray.reduce((a, b)=> a + b);// The answer is 29
var even =sampleArray.filter(v => v %2==0);// The answer is [4, 0]
var odd =sampleArray.filter(v => v %2!=0);// The answer is [7, 1, 3, 5, 11]
var double =sampleArray.map(v => v *2);// The answer is[14, 8, 2, 0, 6, 10, 22]

An arrow function expression or a fat arrow function are shorter in syntax when compared with function expressions. Arrow function is used to bind the value of this. (It does not binds its own arguments, super, this or new.target). Arrow functions are anonymous.

The yield keyword is used to pause and resume a generator function (function* function keyword with an asterisk defines a generator function that returns a Generator object).

Classes

ES6 classes' syntax is simpler and easier than that of area syntactical sugar over the prototype-based object-oriented pattern. It is a syntactical sugar. One-time declaration makes class patterns easier to use and simplifies the use of class patterns. Classes support constructors, instance, prototype-based inheritance, static methods, and super calls.

Here is an example of writing a class in ES6 and ES5:

//ES5
functionsomeES5Class(fname, age) { // standard way to create an object prototype i.e. constructor function
  this.fname = fname;
  this.age = age;
}

someES5Class.prototype.sayName = function() { //prototype property enables us to add new functions to an existing prototype
  console.log(this.fname);
}

someES5Class.prototype.sayAge = function() { //prototype property enables us to add new functions to an existing prototype
  console.log(this.age);
}

varmyInstance = new someES5Class('Talha', 25); //new keyword is used with a constructor function to create new objects from the same prototype
myInstance.sayName(); //the new method can then be called as a regular member
myInstance.sayAge();

/*Output:
Talha
25*/

//ES6
classsomeES6Class { // ES6 class
  constructor(fname, age) { // a constructor is defined with default parameters
    this.fname = fname;
    this.age = age;
  }

  sayName() { //functions can be added to the class
    console.log(this.fname);
  }

  sayAge() { //functions can be added to the class
    console.log(this.age);
  }
}

varmyInstance = new someES6Class('Talha', 25); //new keyword is used to create new objects from the class
myInstance.sayName(); //functions are the class members and can be called directly
myInstance.sayAge();
/*Output:
Talha
25*/

Enhanced object literals

Object literals is one of the most popular patterns of JavaScript. JSON is based on object literals. The reason for its popularity is that it provides a very quick, short, and neat way to do key:value assignments, define methods, evaluate expressions, and make super calls. ES6 has extended the object literal syntax in various ways. This makes them more useful. Two types of extensions for object literals are explained here.

Property initializer shorthand

Earlier in ECMAScript 5, object literals were a comma-separated collection of name:value pairs. There was a likelihood of duplication while property values were being initialized.

Here is an example:

functioncreateStudent(StudentID, name, class) {
  return {
    StudentID: StudentID,
    name: name,
    class: class,
  };
}

In the preceding example, the createStudent() function creates a student object whose name and class properties are similar to the function parameters. This results in duplication of name and class properties, even though both behave differently.

To correct this, the initializer shorthand property was introduced in ECMAScript 6. This removed all the likelihood of duplication between property names and local variables.

For instance, createStudent() can be revised as follows:

functioncreateStudent(StudentID, name, class) {
  return {
    StudentID,
    name,
    class,
  };
}

In the event that property name will be the same as property estimation, you can simply incorporate property name without colon and value.

If the property of an object literal has no value, the JavaScript engine searches for a variable with a similar name in the surrounding. If the search procedure is successful, the value is assigned to the same party name in object literals.

Method initializer shorthand

With the advent of ECMAScript 6, many things improved, making the work of a web developer simpler. The syntax of writing methods in object literals improved to a great extent. Earlier, in ECMAScript 5, we needed to specify a name and write the complete function definition then and there.

Here is an example:

varcustomer = {
  name: "Samantha",
  logName: function() {
    console.log(this.name);
  }
};

With ECMAScript 6, the syntax became easier to code. Colon and function keywords have been removed. The same example can be rewritten as follows:

varcustomer = {
  name: "Samantha",
  logName() {
    console.log(this.name);
  }
};
person.logName();varobject = {
  // __prototype__
  __prototype__: theProtoTypeObj,
  // Shorthand for 'handler: handler'
  handler,
  // Methods
  toString() {
    // Super calls
    return "x " + super.toString();
  },
  // Dynamic property names
  [ 'property_' + (() => 20)() ]: 20
};

Template strings

Template strings amplify ECMAScript with syntactic sugar to build string. This component is like string introduction highlights in Perl, Python, and so on. You can likewise add a tag to permit redid string development, staying away from and counteracting infusion assaults or building complex information structures from string substance. They also enable us to create domain-specific languages (DSLs) to deal with content in a safe way.

Instead of adding more extending functionality to JavaScript strings, template strings provide a total new approach for string interpolation.

Basics

The simplest format of a template string is as follows:

literal${substitution_variable}literal

This is the most basic form of template strings which performs substitutions.

Template strings are enclosed within backticks (`) instead of single or double quotes. Here is an example:

letbasic_string = `Kung Fu Panda`;

console.log(basic_string);               // "Kung Fu Panda"
console.log(typeofbasic_string);        // "string"
console.log(basic_string.length);        // 13

In this example, a basic_string variable contains a simple JavaScript string. The template string syntax is only used to create the string value, which is then assigned to basic_string.

If there is a need to use a backtick in string, then you can escape it using a backslash ():

letbasic_string = ``Kung Fu` Panda.`;      // `Kung Fu' Panda

Multiline strings

In this type of string, we can add multiple lines in a single line of code. To insert a new line in a string, we have to include within the string manually, as follows:

letmultiline_string = "Kung Fu Panda, 

Releasing in 2016";

console.log(multiline_string);

The output of this is:

Kung Fu Panda
Releasing in 2016

We need to be careful regarding the whitespaces, as whitespaces within backticks are considered to be part of the string. All whitespaces before the second line are considered to be part of the string.

Destructuring assignment

In JavaScript, destructuring means pattern matching. In ES6, we can do efficient pattern matching in objects and arrays. Earlier, this was a long and complicated task. Here are some working examples written in a client console.

Fetching data from objects and arrays is very common in JavaScript. Object properties are usually stored in local variables for instant access. Let's take a look at the following code snippet:

var settings = {
  replay: true,
  save: false
};

// later

varlocalReplay = options.replay,
localSave = options.save;

ES6 made this easier by introducing destructuring assignments, which goes through an object or an array and stores specified values in the local variables. It allows binding using pattern matching for objects and arrays.

Array destructuring

All variables can be initialized and swapped at once instead of the conventional way of creating a temporary variable:

var [ first, last ] = ["one", "hundred"] // initialize
console.log(first + " to " + last); // one to hundred

[first, last] = [last, first] // variable swapping
console.log(first + " to " + last); // hundred to one

Multiple values from a function are returned with ease using array destructuring. We don't have to wrap around an object. To skip variables, you can leave the position of the array element blank:

function dob() {
  return [29, "November", 1990, "Thursday"];
}
var [date, month, year, day] = dob();
console.log("My date of birth is on " + date + " " + month); // My date of birth is on 29 November

Object destructuring

Due to destructuring, variables can also be initialized from an object that is returned from a function even with deeply nested objects.

Destructuring enables variables to be initialized from an object that is returned by a function having deeply nested objects. Just like Array destructuring, we can skip the ones not needed. Here's the working snippet:

function dob() {
  return {
    date: 29,
    month: "November",
    year: 1990,
    time: {
      hour: 12, // nested
      minute: 35,
      meridian: "AM"
    }
  };
}

var { date: d, month: m, time : { hour: h, meridian: p } } = dob();
// h is the nested property while year and minute is skipped

console.log("I was born on " + d + " " + m + " at " + h + " " + p); // I was born on 29 November at 12 AM

Extended parameter handling

Functions are an important and fundamental part of any language. ES6 has introduced a number of incremental improvements in functions. This makes them less error prone and more powerful.

Functions allow any number of parameters to be passed irrespective of the number of parameters in the function definition. There are three types of these parameters that could be passed to functions:

  • Default
  • Rest
  • Spread

Default parameter

ES6 lets us set default parameters. A parameter with a default value is considered optional. It binds trailing parameters to an array:

function multiply(x, y) {
  y = typeofy !== 'undefined' ?  y : 1;

  returnx*y;
}

multiply(10);

Rest parameter

Rest parameters replace the need for arguments and addresses common cases more directly. Rest parameters are indicated by three dots (…) preceding a parameter.

Here is an example showing the rest parameter:

//Rest Parameter
function sum(…nums) {
  var result = 0;
  nums.forEach(function(number) {
    result += number;
  });
  return result;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3)); // 6 

The named parameter becomes an array containing the rest of the parameters. Adding more than one named argument may cause syntax error.

Spread operator

Spread operator is very similar to the rest parameter, but it allows us to split the array to individual arguments, which are then passed to the function as separate arguments.

Here is an example showing the spread operator:

//Spread Operator
functionsum2(a, b, c) {
  return a + b + c;
}
varargs = [1, 2];
console.log(sum(…args, …args, 3)); // 6

Here is an example showing the usage of default, rest, and spread parameters:

function sum() {
  return ;
}
console.log(sum(
(1, 2)
//Spread Operator

//Rest Parameter
//Default Parameter Values
//Default Parameter Values
functioninc(num, increment = 1) {
  returnnum + increment;
}
console.log(inc(2, 2)); // 4
console.log(inc(4)); // 5

Bindings

The let keyword is a new var. The declaration syntax for the let keyword is the same as for var. You can basically replace var with let to declare a variable but keep its scope to the current code:

functiongetCuisine(condition) {

  if (condition) {
    letcuisine = "Mediterranean";

    // other code

    returncuisine;
  }
  else {

    // cuisine does not exist here

    return null;
  }

  // cuisine does not exist here
}

Variables defined using const are considered to be constants, so the value cannot be changed once set. For this reason, every const variable has to be initialized:

// Valid constant
const ITEMS = 10;

// Syntax error: missing initialization
const ITEM;

Iterators and the for...of operator

We use iterators to allow customization of an object's iteration method/behavior, such as CLRIE numerable or Java Iterable. Generalize the for..in operator to custom iterator-based iteration with for..of. Iterators are an important feature of ECMAScript 6. When used in combination with new array methods and new types of collections (for example, sets and maps), iterators become even more important for the efficient processing of data.

Fibonacci numbers, or the Fibonacci arrangement, are the numbers in the accompanying whole number succession:

let fibonacci = {
  [Symbol.iterator]() {
    let x = 0, y = 1;
    return {
      next() {
        [x, y] = [y, x + y];
        return { done: false, value: y }
      }
    }
  }
}

for (vari of fibonacci) {
  // truncate the sequence at 3000
  if (i> 3000)
  break;
  console.log(i);
}

Generators

Custom iterators are a useful tool but it requires careful programming so that it can maintain its internal state explicitly. ES6 introduced generators which provide a powerful alternative. Generator allows us to create an iteration algorithm by writing a single function. This single function is able to maintain its own state.

A generator is a function that returns an iterator. The generator functions are denoted by embedding an asterisk (*) after the function keyword. A normal function becomes a generator if it contains a yield expression and uses function* syntax.

Tip

It doesn't matter whether there is space between the function keyword and the asterisk.

The yield keyword is utilized within the generators function to indicate the qualities that the iterator must return when the next() method is called. So, in the event that you need to return unique values for each progressive call to next():

We can convert the previous iterator example to use a generator, as shown here:

let fibonacci = {
  *[Symbol.iterator]() {
    let prex = 0, cury = 1
    for (;;) {
      [ prex, cury ] = [ cury, prex+curv ] = [
        yield cury
    }
  }
}

for (let ni of fibonacci) {
  if (ni> 3000)
  break
  console.log(ni)
}

Better Unicode support

ES6 supports Unicode, including new Unicode literal form in strings, new RegExp u mode to handle code points, as well as new APIs to process strings at the 21-bit code points level. These updates enable us to create global apps in JavaScript. ECMAScript 6 enforces encoding of strings in UTF.

The supported Unicode examples are as follows:

// same as ECMAScript 5
"â–¯".length == 2

// new RegExpbehaviour, opt-in 'u'
"â–¯".match(/./u)[0].length == 2

// new form
"u{1D306}"=="â–¯"=="uD834uDF06"

// new String ops
"â–¯".codePointAt(0) == 0x20BB7

// for-of iterates code points
for(var c of "â–¯") {
  console.log(c);
}

Modules

ECMAScript 6 enables us to export and import symbols to and from modules without polluting the global namespace. It provides added support for modules for component definition. Runtime behavior is defined by a host-defined default loader. It is an implicitly asynchronous model; no code is executed until the necessary modules are available and processed:

export function sum(x, y, {
  return x + y
}

console.log("4Ï€ = " + math.sum(math.pi, math.pi, math.pi, math.pi));

console.log("2Ï€ = " + sum(pi, pi));

Some additional features include export default and export *, as shown in the following code snippet:

exportvar e = 2.71828182846;

export default function(x) {
  returnMath.log(x);
}
console.log("2Ï€ = " + ln(e)*pi*2);

Module loaders

Module loaders are used primarily to resolve module specifiers, loading modules, and so on. They are responsible for downloading the required modules and binding them asynchronously. This brings to light the dependencies of a client script. The constructor is Reflect.Loader.

Module loaders support:

  • Compilation hooks
  • Nested virtualization
  • Dynamic loading
  • Global namespace isolation
  • State isolation

Loader methods

  • System.module(source, options?): This is used to assess the JavaScript code in source to a module (which is delivered and returned non-concurrently by means of a guarantee)
  • System.set(name, module): This is used for the registration of the module created by System.module()
  • System.define(name, source, options?): This is used to assess the module code in source and registers the outcome

We can configure the default module loader, and new loaders can be constructed to evaluate and load code in isolated or constrained contexts:

System.import('libraries/math').then(function(mx) {
  console.log("Ï€ = " + (mx.pi));
});

// Create execution sandboxes – new Loaders
var loader = new Loader({
  global: fixup(window)
});
loader.eval("console.log('live to code!');");

// Directly manipulate module cache
System.get('jquery');
System.set('jquery', Module({$: $}));

Collections

Collections are used to create unique values collections of any type in JavaScript. In a collection of values, you can also add and remove values. There is no direct access to values in collection, and these are of array type.

In ECMAscript 6, collections are a new efficient way to store data. JavaScript arrays are similar to other programming language arrays with index. By use of these arrays, you can pull double and triple data and also stack data. There are many new types of collections in JavaScript. Here are some examples:

  • Sets
  • Maps
  • WeakMap
  • WeakSet

Sets

A set has a unique collection of values. The unique values of a set are also of object reference types. Values in sets cannot be duplicated. Before you access values from a set, you need to check whether the values are present or not.

We can add values in a set and also check the size of values in a set. Here is an example:

Var students=new set();
Students.add(10);
Students.add("Ali");

Maps

A map object is a key/value map. Any value in map may be used as a key or a value. Elements can iterate in a map in an insertion order, and it returns an array of a value or a key. There are two properties of map:

  • Map.length: Returns the number of elements in a map
  • Map.prototype: The Map.prototype property represents the prototype for the map constructor

Here are some of the methods of the map object.

Map.prototype.clear()

The clear() method removes all elements from a map object.

Returns

It returns nothing.

Parameter

There is no input parameter.

Description

After using this function, everything that we have initialized on map will be erased. The function has no parameter and returns nothing as it wipes out everything.

Here is an example of this method:

varmyMap=newMap();
myMap.set("pine","apple");
myMap.set(1,"apple");

myMap.size;// 2
myMap.has("cone");// will return false

myMap.has("pine")// will return true

Map.prototype.delete()

The delete() method removes the specified element from a Map object.

Returns

It returns true if a component in the map object existed and has been evacuated. It returns false if the component does not exist.

Parameter

A key is required. The key here is basically the element to be removed.

Description

This is different from map.prototype.clear() as it clearly removes a specific element instead of deleting every element on the map. We pass a key (the element to be deleted), and the function returns true or false, depending on the key.

Here is an example of this method:

varmyMap=newMap();
myMap.set("pine","apple");

myMap.delete("apple");// Returns true. Successfully removed.
myMap.has("apple");// Returns false. The "apple" element is no longer present.

Map.prototype.entries()

This function is used to tell us about the key and value of elements on map.

Returns

It returns a new iterator object that contains a key and a value for every element on the map.

Parameter

There are no input parameters.

Description

This function is utilized for letting us know about the key and value of components on map.

Here is an example of this method:

varmyMap=newMap();
myMap.set("0","pine");
myMap.set(1,"apple");
myMap.set({},"cone");

varmapIter=myMap.entries();

console.log(mapIter.next().value);// ["0", "pine"]
console.log(mapIter.next().value);// [1, "apple"]
console.log(mapIter.next().value);// [Object, "cone"]

Map.prototype.forEach()

The forEach method executes the given callback once to every key/value pair in the map object.

Returns

It returns nothing.

Parameter

There are three parameters: the element value, element key, and the map object being traversed.

Description

The forEach strategy executes the given callback once to every key of the guide that really exists. It is not conjured for keys that have been erased. Nonetheless, it is executed for values that are available; however, they have the value defined.

Here is an example of this method:

functionlogMapElements(value, key, map) {
  console.log("m["+ key +"] = "+ value);
}
Map([["foo",3],["apple",{}],["cone", undefined]]).forEach(logMapElements);
// logs:
// "m[pine] = 3"
// "m[apple] = [object Object]"
// "m[cone] = undefined"

Map.prototype.get()

A specific element from the map is returned using the get() method.

Returns

It returns the key that is used as a parameter (only if it is found in map); or else, it returns an error message.

Parameter

It requires a key that is to be returned from the map.

Description

We input a key that we want to find in the map, and the function returns it. It is used when we want to get the value of an element.

Here is an example of this method:

varmyMap=newMap();
myMap.set("apple","pine");

myMap.get("apple");// Returns "apple".
myMap.get("cone");// Returns undefined.

Map.prototype.has()

The function returns true (Boolean value) if the element exists and false if it does not.

Returns

It returns true if a component with the specified key exists in the map object. If not found, it returns false.

Parameter

A key is required.

Description

We pass a key in the function to check whether a certain element exists in the map or not. If the element exists, true is returned; otherwise, false is returned.

An example of this method is shown here:

varmyMap=newMap();
myMap.set("apple","pine");

myMap.has("apple");// returns true
myMap.has("cone");// returns false

Map.prototype.keys()

It returns keys for every element in the map.

Returns

It returns a new object that contains the keys of all elements on the map.

Parameter

There is no input parameter.

Description

The keys() strategy gives back another iterator object that contains the keys for every component in the map object in the insertion order.

An example of this method is shown here:

varmyMap=newMap();
myMap.set("0","pine");
myMap.set(1,"apple");
myMap.set({},"cone");

varmapIter=myMap.keys();

console.log(mapIter.next().value);// "0"
console.log(mapIter.next().value);// 1
console.log(mapIter.next().value);// Object

Map.prototype.set()

This is the procedure to add a new element on map.

Returns

It returns the map object.

Parameter

This is the key of the element to be added on map.

Description

The set() strategy includes another component with a predetermined key and value to a map object.

An example of this method is shown here:

varmyMap=newMap();

// Add new elements to the map
myMap.set("apple","pine");
myMap.set(1,"pineapple");

// Update an element in the map
myMap.set("apple","custard");

Map.prototype.values()

This is the method to get a new object containing values of each element.

Returns

It returns an object that has values of all components on map.

Parameter

There is no input parameter.

Description

The values() technique gives back another iterator object that contains the values for every component in the map object in the insertion manner.

Here is an example of this method:

varmyMap = new Map();

varkeyObj = {},
keyFunc = function () {},
keyString = "This is a sample string";

// setting the values
myMap.set(keyString, "value associated to 'This is a sample string'");
myMap.set(keyObj, "value associated to a keyObj");
myMap.set(keyFunc, "value associated to a keyFunc");

myMap.size; // 3

// getting the values
myMap.get(keyString);    // "value associated to 'This is a sample string'"
myMap.get(keyObj);       // "value associated to a keyObj"
myMap.get(keyFunc);      // "value associated to a keyFunc"

myMap.get("a string");   // "value associated to 'This is a sample string'"
// because keyString === 'a string'
myMap.get({});           // undefined, because keyObj !== {}
myMap.get(function() {}) // undefined, because keyFunc !== function () {}

WeakMap

It is the same as map, but there is some difference in it. It only accepts objects as keys. Primitive data types are not allowed in WeakMap. There is no garbage collection in a WeakMap because it doesn't reference to an object acting like a key. As a result of these differences, there is no method to access keys in WeakMap.

Note

Keys in WeakMap are not enumerable, which means that there is no method to give you a list of keys. There is size property available in WeakMap.

Here is an example:

varmyWeakMap1 = new WeakMap(),
myWeakMap2 = new WeakMap(),
varo1 = {},
o2 = function(){},
o3 = window;

myWeakMap1.set(o1, 37);
myWeakMap1.set(o2, "pineapple");
myWeakMap2.set(o1, o2); 
myWeakMap2.set(o3, undefined);
myWeakMap2.set(myWeakMap1, myWeakMap2);

myWeakMap1.get(o2); // "pineapple"
myWeakMap2.get(o2); // undefined, because there is no value for o2 on myWeakMap2
myWeakMap2.get(o3); // undefined, because that is the set value

myWeakMap1.has(o2); // will return true
myWeakMap2.has(o2); // will return false
myWeakMap2.has(o3); // will return true

myWeakMap1.has(o1); // will return true
myWeakMap1.delete(o1);
myWeakMap1.has(o1); // will return false

WeakMap.prototype.clear()

This is used to remove all elements from the WeakMap. This is obsolete now, but is, however, still used in a few browsers.

Returns

It returns the key of the element to be removed from the WeakMap object.

Parameters

This is t key of the element to be removed from the WeakMap object.

Description

Here is an example:

varwm = new WeakMap();
varobject = {};

wm.set(object, "pine");
wm.set(window, "apple");

wm.has(object); // will return true
wm.has(window); // will return true

wm.clear();

wm.has(object)  // will return false
wm.has(window)  // will return false

WeakMap.prototype.delete()

This method is used to remove a specific object from WeakMap.

Returns

It returns true if an element in the WeakMap object has been removed successfully.

Parameters

This is the key of the element to remove from the WeakMap object.

Description

The delete() method removes the specified element from a WeakMap object.

Here is an example:

varwm = new WeakMap();
wm.set(window, "pineapple");

wm.delete(window); // Returns true. Successfully removed.

wm.has(window);    // Returns false. The window object is no longer in the WeakMap.

WeakMap.prototype.get()

This method is used to retrieve a specific object from WeakMap.

Returns

It returns the element associated with the specified key or is undefined if the key can't be found in the WeakMap object.

Parameters

This is the key of the element to return from the WeakMap object.

Description

The key of the element to return from the WeakMap object.

Here is an example:

varwm = new WeakMap();
wm.set(window, "pine");

wm.get(window); // Returns "pine".
wm.get("apple");  // Returns undefined.

WeakMap.prototype.has()

This method is used to check whether the specified object exists in WeakMap.

Returns

It returns true if an element with the specified key exists in the WeakMap object; otherwise it returns false.

Parameters

It is the key of the element to test for presence in the WeakMap object.

Description

The has() method returns a Boolean indicating whether an element with the specified key exists in the WeakMap object or not.

Here is an example:

varwm = new WeakMap();
wm.set(window, "pine");

wm.has(window); // returns true
wm.has("apple");  // returns false

WeakMap.prototype.set()

This method is used to add an object to a specific location.

Returns

The WeakMap object.

Parameters
  • Key: The key of the element to add to the WeakMap object
  • Value: The value of the element to add to the WeakMap object
Description

The set() method adds a new element with a specified key and value to a WeakMap object.

Here is an example:

varwm = new WeakMap();
varobject = {};

// Add new elements to the WeakMap
wm.set(object, "pine").set(window, "apple"); // chainable

// Update an element in the WeakMap
wm.set(object, "cone");

Weakset

This is a collection of objects that don't stop its elements from being garbage collected. There is no looping, iteration, and learning in WeakSet. It has three methods.

WeakSet.prototype.add(someValue)

This method appends a new object at the end of the WeakSet.

Returns

The WeakSet.prototype.add(someValue) method returns Nothing

Parameter

The object to add to the WeakSet collection.

Description

The add() method appends a new object to the end of a WeakSet object.

An example of this method is as follows:

varmyWeakSet=newWeakSet();

myWeakSet.add(window);// add the window object to the WeakSet created above

myWeakSet.has(window);// will return true

WeakSet.prototype.delete(someValue)

This method removes the specified object from WeakSet.

Returns

Returns true if the value is found in WeakSet and is deleted. Returns false if the value is not found.

Parameter

The value to be deleted is sent as a parameter.

Description

The delete() strategy expels the predefined element from a WeakSet object. It is used while we need to delete some element from WeakSet.

An example of this method is as follows:

varmyWeakSet=newWeakSet();
varmyObject={};

myWeakSet.add(window);

myWeakSet.delete(myObject);// Will return false
myWeakSet.delete(window);// Will return true.

myWeakSet.has(window);// Will return false.

WeakSet.prototype.has(someValue)

This method will return true if the object exists in WeakSet; otherwise, false is returned.

Returns

It returns true if a component with the predefined value exists in the WeakSet object; otherwise, it returns false.

Parameter

Requires a value that is to be searched.

Description

The has() technique gives back a Boolean demonstrating whether an item exists in WeakSet or not.

An example of this method is shown here:

varws=newWeakSet();
varobject={};
ws.add(window);

mySet.has(window);  // will return true
mySet.has(object);  // will return false

It has only arbitrary values. References of objects are held in a weak manner in a WeakSet object. They can also be garbage collectors. In WeakSet, there is no list of current objects because of the garbage collector. These objects are not enumerable.

Here is an example:

// Sets
varmySet = new Set();
mySet.add("apple").add("candy");
mySet.size === 2;
mySet.has("hello") === false;

// Maps
varmyMap = new Map();
myMap.set("boy", 27);
myMap.set(f, 25);
myMap.get(f) == 25;

// Weak Maps
varmyWeakMap = new WeakMap();
myWeakMap.set(s, { extra: 99 });
myWeakMap.size === undefined

// Weak Sets
varmyWeakSet = new WeakSet();
myWeakSet.add({ data: 99 });

Proxies

Proxies enable object creation with a wide range of behaviors available to host objects. They can be used for object virtualization, interception, logging/profiling, and so on. Proxies provide developers with an unprecedented control over objects and unlimited possibilities to define new interaction patterns.

Here is an example:

vartargetObject = {};
varhandlerObject = {
  get: function (receiver, book) {
    return `Title, ${name}!`;
  }
};

varproxyObject = new Proxy(target, handler);
proxyObject.world === 'Lahore!';

// Proxying a function object
vartargetObject = function () { return 'Target, I am'; };
varhandlerObject = {
  apply: function (receiver, ...args) {
    return 'Le proxy';
  }
};

var p = new Proxy(target, handler);
p() === 'Le proxy';

Symbols

A symbol is a unique type which can be used as an identifier for object properties. The symbol object is an implicit object wrapper for the symbol primitive data type.

Here is how you can create a new primitive symbol:

var symb = Symbol(); 

OR

var symb = Symbol('abc');

The preceding code creates two new symbols. Symbol('abc') does not force converts abc into an object but creates a new separate object.

Symbol('abc') === Symbol('abc'); //false

Using Symbol() with new keyword will throw a type error.

var symb = new Symbol(); // TypeError

This prevents creation of an explicit Symbol wrapper object instead of a new symbol value. Creating an explicit wrapper object around primitive data types were only supported until ES5. However, existing primitive wrapper objects like new Boolean, new String and new Number can still be created for legacy reasons.

And if it is necessary to create Symbol wrapper object, you can use the Object() function:

var symb = Symbol("abc");
typeof symb;     // "symbol" 
var symbObj = Object(symb);
typeof symbObj;  // "object"

The Object.getOwnPropertySymbols() method returns an array of symbols and lets you find symbol properties on a given object.

Here is an example:

varSomeClass = (function() {

  var key = Symbol("key");

  functionSomeClass(privateData) {
    this[key] = privateData;
  }

  SomeClass.prototype = {
    doStuff: function() {
      ... this[key] ...
    }
  };

  returnSomeClass;
})();

var c = new SomeClass("bye")
c["key"] === undefined

Note

The ECMAScript 6 standard uses a special notation to indicate symbols, prefixing the identifier with @@, such as @@create.

Subclassable built-ins

In ECMAScript 6, built-ins such as Date, Array, and DOM elements can be subclassed. Object construction for a function named Ctor now uses two phases:

  • Call Ctor[@@create] to allocate the object and install any special behavior
  • Invoke constructor on new instance to initialize it

The known @@create symbol is available via Symbol.create. Built-ins now expose their @@create syntax explicitly.

Here is an example:

// Pseudo-code of Array
classSomeArray {
  constructor(...args) { /* ... */ }
  static [Symbol.create]() {

  }
}

// User code of Array subclass
classSomeArray extends Array {
  constructor(...args) { super(...args); }
}

// Two-phase 'new':
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
vararr = new SomeArray();
arr[1] = 123;
arr.length == 1

Promises

ECMAScript 6 introduced promises. It is a library used for asynchronous programming. It is a first-class representation of a value that may be made available in the future. Many existing JavaScript libraries already use promises.

Some of the methods for promises in ES6 are mentioned here.

Promise.All()

This method returns a promise that is resolved once all the promises in the iterable argument have been resolved. In the case of a rejection, it returns with the reason of the first-passed promise that was rejected.

Returns

The Promise.All() method returns nothing.

Parameter

An iterable object, such as an array.

Description

Promises returns result as an array of values. If any value in the array is not a promise, then it is converted using Promise.resolve. If any of the passed in promises rejects, then all promise are rejected and the reason of rejection of a promise is returned. It discards all other promise whether they have been resolved or not. If an empty array is passed, then this method resolves immediately.

An example of this method is shown here:

varprom1 = 6000;
varprom2 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, "Here");
}); 

Promise.all([prom1, prom2]).then(function(values) {
  console.log(values); // [6000, "Here"]
});

Promise.prototype.catch()

This method is used only in cases where objects are rejected. It works the same as promise.prototype.then().

Returns

The promise.prototype.catch() method returns nothing.

Parameter

  • One rejected: A function called when the promise is rejected. This function has one argument, the rejection reason.

Description

The catch() technique gives back a promise and manages rejected cases. It behave similar as calling Promise.prototype.then(undefined, onRejected).

An example of this method is as follows:

varprom1= new Promise(function(resolve, reject) {
  resolve('This was Successful!!');
});

prom1.then(function(value) {
  console.log(value); // "This was Successful!!"
  throw 'oh, no!';
}).catch(function(e) {
  console.log(e); // "Error found"
}).then(function() {
  console.log('Catch Done!');
}, function () {
  console.log('Not fired due to the catch');
});

Promise.resolve(value)

This method returns a promise object that is resolved by the specified value. If the value is associated to a then method, the returned promise will move to the then method, adopting its final state. Otherwise, the returned promise will be fulfilled with the specified value.

Returns

The promise object that is resolved with the given value.

Parameter

Let's take a look at the following parameters and their use:

  • onFulfilled: A function called when the Promise is fulfilled
  • onRejected: A function called when the promise is rejected

Description

The Promise.resolve(value) system gives back a Promise question that is determined with the given quality. On the off chance that the quality is a then able (that is, has a then technique), the returned promise will follow that then able, adopting its possible state.

The then() technique gives back a Promise. It takes two contentions: callback capacities for the achievement and disappointment instances of the Promise.

Using the then method

An example of this method is as follows:

varprom1=newPromise(function(resolve, reject) {
  resolve("This was a Success!");
  // or
  // reject ("Error Found Try Again!");
});

prom1.then(function(value) {
  console.log(value);//This was a Success!
},function(reason){
  console.log(reason);// Error Found Try Again!
});
Chaining

As the then() method returns a Promise, you can easily chain then calls:

varp2=newPromise(function(resolve, reject) {
  resolve(1);
});

p2.then(function(value) {
  console.log(value);// 1
  return value +1;
}).then(function(value) {
  console.log(value);// 2
});

p2.then(function(value) {
  console.log(value);// 1
});

You can also use chaining to implement one function with a Promise-based API on top of another such function:

functionfetch_current_data() {
  returnfetch("current-data.json").then((response)=> {
    if(response.headers.get("content-type")!="application/json") {
      thrownewTypeError();
    }
    var j =response.json();
    // maybe do something with j
    return j;// fulfillment value given to user of
    // fetch_current_data().then()
  });
}

Promise.reject(value)

This function returns a promise object that is rejected because of the passed value/reason.

Returns

The Promise.reject() method returns a simple output telling the reason for rejection.

Parameter

Reason why this promise is rejected.

Description

The static Promise.reject() function capacity gives back a Promise that is rejected. For troubleshooting purposes and specific mistake finding, it is helpful to make the reason an instance of error.

An example of this method is shown here:

Promise.reject("Testing Promise reject").then(function(reason) {
  // not called
},function(reason) {
  console.log(reason);// "Testing Promise reject"
});

Promise.reject(newError("fail")).then(function(error) {
  // not called
},function(error) {
  console.log(error);// Stacktrace
});

Promise.race(value)

This function returns a promise that is resolved or rejected the same way as the promises passed in iterable, with the value or reason from that promise.

Returns

The Promise.race() function returns a promise.

Parameter

An iterable object, such as an array.

Description

The race function gives back a Promise that is settled the same route as the initially passed Promise to settle. It determines or rejects, whichever happens first.

An example of this method is as follows:

varmyPromise1=newPromise(function(resolve, reject) {
  setTimeout(resolve,800,"first");
});
varmyPromise2=newPromise(function(resolve, reject) {
  setTimeout(resolve,300,"second");
});

Promise.race([myPromise1,myPromise2]).then(function(value) {
  console.log(value);// "second"
  // Both resolve, but myPromise2 is faster
});

Core math library APIs

ECMAScript 6 has made several new extensions to the prebuilt libraries, including core Math libraries, arrays, string helpers, and Object.assign for copying. These new methods help in speeding up the execution process, hence resulting in enhancing the performance of applications that may perform calculations and string manipulation. It also improves the speed of applications that must perform many calculations and string manipulations.

Numerous new library increases, including core Math libraries, array conversion helpers, string helpers, and Object.assign for copying. An example of using the Core Math Library APIs is as follows:

Number.EPSILON
Number.isInteger(Infinity) // will return false
Number.isNaN("NaN") // will return false

Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2

"Neptune".includes("cd") // This will return false
"Mars".repeat(4) // This will be "MarsMarsMarsMars"

Array.from(document.querySelectorAll('*')) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(2, 1) // [0,2,2]
[24, 14, 23, 57, 89, 75, 33].find(x => x == 33) // 33
[24, 14, 23, 57, 89, 75, 33].findIndex(x => x == 14) // 1
[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
["x", "y", "z"].entries() // iterator [0, "x"], [1,"y"], [2,"z"]
["x", "y", "z"].keys() // iterator 0, 1, 2

Binary and octal literals

ECMAScript 6 introduced binary and octal literal notations, for binary (b) and octal (o). Both these notations are a little similar to hexadecimal literal notation for prepending 0x or 0X to a value.

The new octal literal format begins with 0o or 0O, while the new binary literal format begins with 0b or 0B. Each literal type must be followed by one or more digits; 0-7 for octal and 0-1 for binary. Here's an example:

// ECMAScript 6
varvalue11 = 0o65;      // 53 in decimal
varvalue22 = 0b100;     // 4 in decimal

0b111110111 === 503 // will return true
0o767 === 503 // will return true

Reflect API

The reflect object is a single object that contains functions related to the reflection API. As the name suggests, it is merely a reflection of the objects so that one can observe them closely, regardless of who the object was created by. The reflect object is not a function object. It does not have a constructor method. It cannot be invoked as a function, because it does not have a call method.

Reflect API is known to be the inverse of Proxy API.

Here is a list of methods a reflect object has.

Reflect.get(target, prop, [receiver])

This method allows you to get the property of an object. This method is similar to property accessors syntax (object[propertyKey]).

Returns

The reflect object returns the value of property.

Parameter

The parameters are target objects on which to get property, the name of property, and the value.

Description

The static Reflect.get() method works like getting a property from an object (target[propertyKey]) as a function.

An example of the get method is as follows:

// Object
varobject={a:4,b:5};
Reflect.get(object,"b");// 5

// Array
Reflect.get(["first","second"],1);// "second", since array starts with 0 index

// Proxy with a get handler
var x ={p:9};
varobject=newProxy(x, {
  get(a,b,c){returnb +"meow";}
});
Reflect.get(object,"woof");// "woofbar"

Reflect.set(target, prop, value, [receiver])

This method allows you to set a property of an object. This method is also similar to property accessor syntax.

Returns

The Reflect.set(target, prop, value, [receiver] returns a Boolean value indicating whether property was successful or not.

Parameter

Parameters are target objects, name of the property, the value to set, and the receiver.

Description

The static Reflect.set() strategy works like setting a property on an item.

An example of this method is shown here:

// Object
varobject={};
Reflect.set(object,"property","value");// will return true
object.property;// "value"

// Array
vararr=["cow","cow","cow"];
Reflect.set(arr,1,"goat");// will return true
arr[1];// "goat"

// It can truncate an array.
Reflect.set(arr,"length",1);// will return true
arr;// ["goat"];

// With just one argument, propertyKey and value are "undefined".
varobject={};
Reflect.set(object);// will return true
Reflect.getOwnPropertyDescriptor(object,"undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }

Reflect.has(target, prop)

This method allows you to check whether an object holds a specific property. This method is similar to the in operator.

Returns

The Reflect.has(target, prop) returns a Boolean value indicating whether the target has a property or not.

Parameter

The target object and the property key (name of property to check) is passed.

Description

The static Reflect.has() technique works like the in operator as a function.

An example of this method is shown here:

Reflect.has({a:0},"a");// will return true
Reflect.has({a:0},"b");// will return false

// returns true for properties in the prototype chain
Reflect.has({a:0},"toString");

// Proxy with .has() handler method
object=newProxy({}, {
  has(s,d){returns.startsWith("cat");}
});
Reflect.has(object,"catastrophe");// will return true
Reflect.has(object,"camel");// will return false

Reflect.apply(target, receiver, args)

This method is used to call a target function with a specified set of arguments.

Returns

The Reflect.apply(target, receiver, args) method returns nothing.

Parameter

Target function to call. thisArgument and ArgumentList is passed as parameters.

Description

The static Reflect.apply() technique calls an objective function with specified arguments.

An example of this method is shown here:

Reflect.apply(Math.floor, undefined,[3.999]);
// 3;

Reflect.apply(String.fromCharCode, undefined,[80, 97, 107, 105, 115, 116, 97, 110]);
// "Pakistan"

Reflect.apply("".charAt,"stars",[2]);
// "a"

Reflect.construct(target, args)

This method allows you to call a constructor function with multiple arguments. It is just like calling new function (…args).

Returns

The Reflect.construct(target, args) returns nothing.

Parameter

The target function to be called, an argument list, and the new target (constructor to be used) are parameters.

Description

The Reflect.construct method permits you to conjure a constructor with a variable number of contentions (which would likewise be conceivable utilizing the spread operator consolidated with the new operator).

An example of this method is shown here:

Using Reflect.construct():

var d =Reflect.construct(Date,[2015,1,5]);
dinstanceofDate;// will return true
d.getFullYear();// 2015

Using newTarget:

functionmyConstructor(){}
var result =Reflect.construct(Array,[],myConstructor);

Reflect.getPrototypeOf(result);// myConstructor.prototype
Array.isArray(result);// will return true

Reflect.getOwnPropertyDescriptor(target, prop)

This method is just like Object.getOwnPropertyDescriptor(). This method returns a property descriptor of a specific property if it exists on an object; otherwise, undefined is returned. The only difference between these two is the way non-object targets are handled.

Returns

The Reflect.getOwnPropertyDescriptor(target, prop) method returns a property descriptor object.

Parameter

The target object in which to look for property, and property key (name of the property to be applied) are the parameters.

Description

The Reflect.getOwnPropertyDescriptor system gives back a property descriptor of the given property in the event that it exists on the object, indistinct something else undefined is returned if property does not exists. The main contrast to Object.getOwnPropertyDescriptor() is the manner by which non-object targets are taken care of.

An example of this method is shown here:

Using Reflect.getOwnPropertyDescriptor():

Reflect.getOwnPropertyDescriptor({a:"bye"},"a");
// {value: "bye", writable: true, enumerable: true, configurable: true}

Reflect.getOwnPropertyDescriptor({x:"bye"},"y");
// undefined

Reflect.getOwnPropertyDescriptor([],"length");
// {value: 0, writable: true, enumerable: false, configurable: false}

Difference to Object.getOwnPropertyDescriptor():

If the first argument to this method is not an object (a primitive), then it will cause a TypeError. With Object.getOwnPropertyDescriptor, a non-object first argument will be coerced to an object at first:

Reflect.getOwnPropertyDescriptor("woof",0);
// TypeError: "woof" is not non-null object

Object.getOwnPropertyDescriptor("dummy",0);
// { value: "d", writable: false, enumerable: true, configurable: false }

Reflect.defineProperty(target, prop, desc)

This method is similar toObject.defineProperty(). This method allows us to modify the property of an object. The Object.defineProperty() method returns an object or returns a type error if the property is not defined successfully. The Reflect.defineProperty() method returns true if the property was defined successfully. Otherwise, it returns false.

Returns

The Reflect.defineProperty(target, prop, desc) method returns a Boolean demonstrating regardless of whether the property was effectively characterized.

Parameter

Target object, property key, and attributes are the parameters.

Description

The Reflect.defineProperty technique permits the exact expansion to or change of a property on an object. For more subtle elements, see the Object.defineProperty, which is comparative. Object.defineProperty gives back the objects or tosses TypeError if the property has not been effectively characterized. Reflect.defineProperty, then again, essentially gives back a Boolean demonstrating regardless of whether the property was effectively characterized.

An example of this method is shown here:

Using Reflect.defineProperty():

http://haseeb.deeurl.com/client-demos/everydayadvice/v3/={};
Reflect.defineProperty(object,"x",{value:7});// will return true
object.x;// 7

Checking if property definition has been successful:

With Object.defineProperty, which returns an object if successful or throws a TypeError otherwise, you would use a try...catch block to catch any error that occurred while defining a property. As Reflect.defineProperty returns a Boolean success status, you can just use an if...else block here:

if(Reflect.defineProperty(target, property, attributes)) {
  // will return success
}
else{
  // will return failure
}

Reflect.getPrototypeOf(target)

This method returns a prototype of the specified object. It is similar to the Object.getPrototypeOf() method.

Returns

The Reflect.getPrototypeOf(target) method returns the prototype of object or null.

Parameter

The target object for which we need the prototype is passed as a parameter.

Description

The static Reflect.getPrototypeOf() method is the same technique as Object.getPrototypeOf(). It gives back the model (that is, the estimation of the inside [[Prototype]] property) of the predetermined item.

An example of this method is shown here:

Reflect.getPrototypeOf({});// Object.prototype
Reflect.getPrototypeOf(Object.prototype);// will return null
Reflect.getPrototypeOf(Object.create(null));// will return null

Reflect.setPrototypeOf(target, newProto)

This method sets the prototype of object to another object or to null. This method is the same as the Object.setPrototypeOf() method.

Returns

The Reflect.setPrototypeOf(target, newProto) method returns a Boolean showing regardless of whether the model was effectively set.

Parameter

The target object and prototype are parameters.

Description

The Reflect.setPrototypeOf method changes the prototype (that is, the value of the internal [[Prototype]] property) of the specified object.

An example of this method is shown here:

Reflect.setPrototypeOf({},Object.prototype);// will return true
Reflect.setPrototypeOf({},null);// will return true

Reflect.setPrototypeOf(Object.freeze({}),null);// will return false

var target ={};
varprototype=Object.create(target);
Reflect.setPrototypeOf(target,prototype);// will return false

Reflect.deleteProperty(target, prop)

This method is used to delete properties from an object. This method is similar to the delete operator as a function.

Returns

The Reflect.deleteProperty(target, prop) method returns a Boolean value telling us whether the property is deleted or not.

Parameter

The target object and the name of the property to be deleted are parameters.

Description

The Reflect.deleteProperty method permits you to erase a property on an object. It returns boolean value indicating if the property was successfully removed or not, regardless of whether the property was effectively characterized. It is almost similar to the non-strict delete operator.

An example of this method is shown here:

varobject={a:11,b:12};
Reflect.deleteProperty(object,"a");// will return true
object;// { y: 12 }

vararr=[11,12,13,14,15];
Reflect.deleteProperty(arr,"3");// will return true
arr;// [11, 12, 13, , 15]

// Returns true if no such property exists
Reflect.deleteProperty({},"bar");// will return true

// Returns false if a property is unconfigurable
Reflect.deleteProperty(Object.freeze({bar:1}),"bar");// will return false

Reflect.enumerate(target)

This method returns an iterator with enumerable own and inherited properties of the target object.

Returns

Returns an iterator with the enumerable own and acquired properties of the objective object.

Parameter

Target object on which to get property is passed in the function.

Description

The Reflect.enumerate() method returns an iterator with the enumerable own and inherited properties of the target object.

An example of this method is shown here:

varobject={a:98,b:99};

for(var name ofReflect.enumerate(object)) {
  console.log(name);
}
// logs "a" and "b"

Reflect.preventExtensions(target)

This is the same method as Object.preventExtensions(). It prevents us from adding more properties (extensions) to an object.

Returns

Returns a Boolean demonstrating regardless of whether the objective was effectively set to forestall expansions.

Parameter

Target object on which we have to prevent extensions.

Description

The static Reflect.preventExtensions() method keeps new properties from always being added to an object (that is, counteracts future augmentations to the item). It is like Object.preventExtensions(), yet with a few contrasts.

An example of this method is as follows:

varblank={};
Reflect.isExtensible(blank);// === will return true

Reflect.preventExtensions(blank);
Reflect.isExtensible(blank);// === will return false

Reflect.isExtensible(target)

This method allows us to check whether new properties can be added to an object or whether the object is extensible or not. This method is similar to the Object.isExtensible() method.

Returns

A Boolean value indicating whether the target is extensible or not.

Parameter

The target object that has to be checked for its extensibility.

Description

The static Reflect.isExtensible() technique figures out whether an item is extensible (whether it can have new properties added to it). It is like Object.isExtensible(), yet with a few contrasts.

An example of this method is shown here:

var blank ={};
Reflect.isExtensible(blank);

The preceding function will return true.

Reflect.ownKeys(target)

This method returns the object's own property keys.

Returns

The Reflect.ownKeys(target) method returns an array of target objects.

Parameter

Target object from where to get keys.

Description

The static Reflect.set() strategy works like setting a property on an object.

Here is an example of this method:

Reflect.ownKeys({a:5,b:6,c:7});
Reflect.ownKeys([]);

varsymbol=Symbol.for("dirt");
varsymbolb=Symbol.for("sky");
varobject={[symbol]:0,"string":0,"99":0,"4":0,
[symbolb]:0,"100":0,"-7":0,"second string":0};
Reflect.ownKeys(object);

Tail calls

Calls in tail position won't be able to grow the stack without any limits. It helps in making recursive algorithms safe and secure in the safe of unbounded inputs.

Example

The following function produces a factorial of any number passed to it. There is a tail call in the end of the function which recalls the function. Previously, we used to get a stackoverflow error, but ES6 is safe for handling arbitrary inputs.

If the output is out of range, it will simply display infinity:

function factorial(n, acc) {
 'use strict';
 if (n <= 1) return acc;
 return factorial(n - 1, n * acc);
}
console.log(factorial(5, 1)); //120
console.log(factorial(200, 1)); //Infinity

// Stack overflow in most implementations today,
// but safe on arbitrary inputs in ES6
console.log(factorial(10000000, 1));
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.56.12