JavaScript


Creative Commons License
This -JavaScript- tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
Preamble
This tutorial is about basic and advanced features of JavaScript (a.k.a. ECMAScript). Since JavaScript is not statically typed, early fault detection at compilation time is impossible. JavaScript may thus benefit from being substituted by TypeScript (here…). This tutorial further discusses JavaScript 6 & 7 (a.k.a. ECMAScript 2015 & 2016). Key novelties of ECMAScript 2015 are summarized here
Headlines
The big picture: As “The language of Internet”, JavaScript shares such title with Java. The latter rather takes place at the backend while the former dominates at the frontend (as browser native programming language). Things radically changed with Node.js.

JavaScript positioning in programming languages' competition

Rule(s)

Styles of programming

Rule(s)
Contemporary JavaScript file organization requires “ejection” from the inside of HTML files.
Example

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <title>Code management</title>

        <link rel="shortcut icon" href="favicon.ico"/>

        <script src="js/chai.js"></script>
        <script src="js/dat.gui.min.js"></script>

        <!-- Internet connection required: -->
        <script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>

        <script src="js/JavaScript_general_matter.js"></script>

        <script>
            if (typeof chai === "undefined")
                window.alert("STOP: it won't work because 'chai.js' has not been loaded…");
            if (typeof dat === "undefined")
                window.alert("STOP: it won't work because 'dat.gui.min.js' has not been loaded…");
            if (typeof createjs === "undefined")
                window.alert("STOP: it won't work because 'createjs-2015.11.26.min.js' has not been loaded…");
            window.onload = go;
        </script>
    </head>
    <body >
        <canvas id="my_canvas" width="600" height="400"></canvas>
    </body>
</html>
Content Delivery Network (CDN) for JavaScript is the ability to inline download libraries from dedicated sites offered by Google, Microsoft, etc. One popular CDN is https://cdnjs.com.
Example (downloading jQuery from Google)
<!-- Internet connection required: -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
Loading (in sequence) JavaScript libraries in HTML files may involve a lot of manual management: sequence must respect dependencies, asynchronous loading (for performance) must be explicit using async, etc. RequireJS, webpack or Browserify are utilities that avoid such a tricky management.
Rule(s)
Example reusing RequireJS
<!-- 'data-main' attribute tells 'require.js' to load 'UV_mapping_three.js' after 'require.js' loads... -->
<!-- *By construction*, 'UV_mapping_three.js' is loaded in an asynchronous way by 'require.js' -->
<!-- Here, 'async' just embodies the asynchronous loading of 'require.js' itself! -->
<script async data-main="./js/UV_mapping_three" src="./js/require.js"></script>
requirejs(['three'], function (library) {
    window.THREE = library;
    // While 'three.js' may be used from here, one has however to check that the DOM and/or the full window (images, sounds, videos…) are/is loaded.  
});
From JavaScript 6, export and import are native supports to manage modules and their dependencies (further information here…)
Example (UV_mapping_three_js.zip )
<script src="./js/UV_mapping_three.js" type="module"></script>
/** FB_ei.js */
// 'use strict'; // No need when imported...
export var author = {value: "Franck Barbier"};
export default getAuthor; // Only one default export, i.e., import does not require braces!
function getAuthor() {
    return author.value;
};
/** Authoring_ei.js */
// 'use strict'; // No need when imported...
import {author as developer} from "./FB_ei"; // '.js' may be omitted...
import getAuthor from "./FB_ei.js";
export {Authoring}; // <=> {Authoring as Authoring};
var Authoring = function () {
    this._author = developer.value ? developer.value : getAuthor();
    …
};
Example
export class C {…} // 'export' must be synch with class declaration!
Illustration: JavaScript modularity
Rule(s)
Example (Export_import.js.zip )
<script src="./js/C.js" type="module"></script>
// 'A.js' file
export let A = "A";
// 'B.js' file
import {A as proxy} from "./A.js";

export let A = proxy;
// 'C.js' file
import {A} from "./B.js";

window.alert("'A' in 'C.js': " + A); // "A" is displayed...
Because of permissivity, it is advised to write JavaScript in strict mode so that the interpreter checks the code at run-time; it accordingly generates errors viewable in the console browser.
Rule(s)
Example
"use strict";
var well_declared_variable = "Strict mode is activated from all statement lines in the rest of this source file!";
ill_declared_variable = 2016; // The absence of 'var' normally raises an error at execution time thanks to the strict mode
Rule(s)
Example
const my_const = "It cannot change!";
my_const = "One says it cannot change!"; // Execution error
if(something) {
    let this_year = 2017; 
} // <- 'this_year' dies right there while 'var' (contrary to 'let') makes the variable living throughout its declaration function
JavaScriptobjects” are either primitive (boolean, number, bigint, string, undefined, and symbol) or, by default, they are created from a prototype that comes to the Object type. Other key non-primitive types are Event, Function, Promise, RegExp, or Error.
Rule(s)
Example (string to number conversion)
 window.console.assert(Number.parseInt("10", 10) === 10);
Example
window.alert(typeof true); // 'boolean'
window.alert(typeof 2016); // 'number'
window.alert(typeof "2016"); // 'string'
var Franck = "Franck";
window.alert(`Hello ${Franck}`); // JavaScript 6 backquotes!
window.alert(Number.MAX_VALUE);
window.console.assert(++Number.MAX_VALUE === Number.POSITIVE_INFINITY);
var o = Object.create(Object.prototype); // <=> 'var o = {};'
window.alert(typeof o); // 'object'

null and undefined

Rule(s)
Example
var x;
window.alert(typeof x); // 'undefined' is displayed
window.alert(typeof null); // 'object'
See also

Numbers (including NaN)

Rule(s)
See also
Rule(s)
Example
const my_bigint = 1234567890123456789012345678901234567890n; // Note 'n' suffix!

JavaScript objects may grow and slim!

Example
var Franck = {};
Object.defineProperty(Franck, "surname", {value: "Barbier", enumerable: true, configurable: true, writable: true});
window.alert(Franck.surname); // 'Barbier' is displayed - One may also access objects' properties as follows: 'Franck["surname"]'

Franck.skill = "JavaScript"; // Dynamic extension
delete Franck.skill; // Dynamic suppression
if ("skill" in Franck === false) window.alert("'Franck.skill' no longer exists…");

Franck.severe = true;
window.alert(JSON.stringify(Franck)); // '{"surname":"Barbier","severe":true}' is displayed
Example
Object.defineProperty(Franck, "nickname", {value: "Bab", enumerable: true, configurable: false, writable: false});
try {
    Franck.nickname = "Other nickname";
} catch (error) {
    window.alert(error.message); // '"nickname" is read-only' is displayed
}
try {
    delete Franck.nickname;
} catch (error) {
    window.alert(error.message); // 'property "nickname" is non-configurable and can't be deleted' is displayed
}

Dealing with PropertyDescriptor

Example
var non_configurable = {insupportable: "C'est la MAAF que je préfère..."};
Object.seal(non_configurable);
delete non_configurable.insupportable; // Bug: 'property "insupportable" is non-configurable and can't be deleted''

The notions of constructor and prototype

Example
const x = {a: "a"};
window.console.assert(x.constructor === Object); // 'Object' function...
window.console.assert(x.prototype === undefined); // Not accessible...
window.console.assert(Object.getPrototypeOf(x) === Object.prototype); // "Prototype inheritance"...

JavaScript offers predefined objects (with predefined properties: attributes and/or functions)

Example
window.alert(JSON.stringify(window.location.hostname)); // '"localhost"' may be displayed
window.alert(window.Math.E); // '2.718281828459045' is displayed
window.alert(window.Math.ceil(Math.E)); // '3' is displayed

The case of this

The way of dealing with this
Example (Miscellaneous.js.zip )
Franck.my_array = [null, 0, "ABC"]; // Arrrgggglll, arrays may contain anything!

Franck.my_array_processing = function () {
    for (let i = 0; i < this.my_array.length; i++) {
        this.my_array[i] = this.severe; // Great, 'this' is set to the appropriate "current" object!
    }
};
Franck.my_array_processing(); // 'this' is inferred here...
window.alert(window.JSON.stringify(Franck)); // '{"surname":"Barbier","nickname":"Bab","severe":true,"my_array":[true,true,true]}'

Franck.my_array_processing = function () { // Erase prior version...
    this.my_array.forEach(function (element) {
        window.alert("typeof 'this' in 'Franck.my_array_other_processing' : " + typeof this); // 'undefined'
        // element = this.severe; // Arrrgggglll, 'this' is NOT set to the appropriate "current" object: 'TypeError: this is undefined' in the console...
    }/*, this*/); // You got some trouble just before? Uncomment!
};
Franck.my_array_processing();

Franck.my_array_processing = function () { // Erase prior version...
    this.my_array.forEach(element => { // 'this' in lambda expression is set *IN A STATIC WAY*
        window.console.assert(Franck === this); // Bingo!
        element = this.severe; // It works!
    }/*, this*/); // No need of injecting 'this' as second argument of 'forEach'
};
Franck.my_array_processing();

Using bind

Example (Miscellaneous.js.zip )
const my_function = function (element) {
    window.console.assert(Franck === this);
    element = this.severe;
};
Franck.my_array_processing = function () { // Erase prior version...
    this.my_array.forEach(my_function.bind(this));
};
Franck.my_array_processing();

if control statement, operators (and other subtleties)

Rule(s)
Example
if(expression) {} // This evaluates to 'true' if 'expression' is not:

        null

        undefined

        NaN

        "" // Empty string

        0

        false
Rule(s)
Example
// 'A || B' returns the value 'A' if 'A' can be coerced into 'true'; it returns 'B' otherwise...
const port = process.env['PORT'] || 8080;
// Alternative:
const port = process.env['PORT'] ? process.env['PORT'] : 8080;
JavaScript has no native support for enumerated types.
Rule(s)
Example
const Medal = Object.freeze({ // No new field, no removable field, no writability, etc.
    Gold: Symbol("Gold"),
    Silver: Symbol("Silver"),
    Bronze: Symbol("Bronze")
});
window.console.assert(Object.isFrozen(Medal));
let award = Medal.Gold;
window.alert(award !== Symbol("Gold")); // 'true' because 'Symbol' objects are unique...
Arrays in JavaScript are, by their flexibility, a core tool to manage collections of elements. Common arrays are instance of the predefined Array type while typed arrays have been recently introduced to (mainly) deal with bit streams (i.e., buffers).
Example (Miscellaneous.js.zip )
let matrix = [[1, 2], [1, 2]];
let norm = 0;
matrix.forEach(function (element) {
    norm += element.reduce(function (sum, element) {
        return sum + element ** 2; // JavaScript 7 only! -> 'return sum + Math.pow(element, 2);'
    });
});
window.alert("Norm: ('forEach')" + Math.sqrt(norm));

norm = 0;
for (let element of matrix) {
    norm += element.reduce(function (sum, element) {
        return sum + element ** 2; // JavaScript 7 only! -> 'return sum + Math.pow(element, 2);'
    });
}
window.alert("Norm ('let'): " + Math.sqrt(norm));

const chromosomes = ["Genetic female - XX","Genetic male - XY"];
window.alert(chromosomes instanceof Array); // 'true' is displayed
window.alert(typeof chromosomes); // 'object' is displayed

chromosomes[-1] = "N'importe quoi !";
window.alert(chromosomes[-1]); // 'N'importe quoi !' is displayed
window.alert("chromosomes.length: " + chromosomes.length); // '3' is displayed!

const diseases = new Array("Turner's syndrome - X","Klinefelter syndrome - XXY");
window.console.assert(diseases.length === 2);

const genetics = [...chromosomes, ...diseases];
window.alert(JSON.stringify(genetics)); // '["Genetic female - XX","Genetic male - XY","Turner's syndrome - X","Klinefelter syndrome - XXY"]' is displayed!

const [given_name, surname] = ['Franck', 'Barbier'];
window.alert(typeof given_name + ": " + given_name); // 'string: Franck' is displayed...

const fb = ['Fr', 'Ba'];
const [gv = '?', sn = '?', nn = '?'] = fb;
window.alert(gv); // 'Fr' is displayed...
Illustration: JavaScript arrays

Sets and maps in JavaScript bring out an enhanced collection support, that is originally based on arrays only.
Rule(s)
Example (currencies.react.zip )
static _Links = [
    {
        path: '/' + 'Currencies',
        component: CurrenciesWrapper,
        data: {material_icon: 'payment'}
    },
    {
        path: '/' + 'New',
        component: CurrenciesController,
        data: {material_icon: 'fiber_new'}
    },
    {
        path: '/' + 'Currencies' + '/' + `${Currencies.Currencies[Currencies.Dollar].iso_code}`,
        component: CurrenciesInformation,
        data: {iso_code: Currencies.Currencies[Currencies.Dollar].iso_code, material_icon: 'attach_money'}
    },
    {
        path: '/' + 'Currencies' + '/' + `${Currencies.Currencies[Currencies.Euro].iso_code}`,
        component: CurrenciesInformation_,
        data: {iso_code: Currencies.Currencies[Currencies.Euro].iso_code, material_icon: 'euro_symbol'}
    }
];
static _Components = [...new Set(CurrenciesMenu._Links.map(link => link.component))]; // 3
Example
// const polynomial = new WeakMap();
// polynomial.set(1, -12); // Bug...
// polynomial.set(39, 8);  // Bug...
const polynomial = new Map();
polynomial.set(1, -12); // OK...
polynomial.set(39, 8);  // OK...
window.alert(polynomial.get(39)); // '8'
JavaScript functions are powerful tools in the sense that they have a first-class status as plain objects. The absence of static typing in JavaScript suppresses any control about functions' arguments and returned objects: their types and number.
Rule(s)
Example
const my_function = function (my_parameter) {
    window.alert("'arguments' is a predefined array that lets the access to the passed arguments: " + arguments.length);
// Forbidden in strict mode (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/):
    window.alert(arguments.callee); // Entire code of 'my_function' is displayed...
    return ++my_parameter;
};
window.alert(my_function(0)); // '1' is displayed
window.alert(typeof my_function); // 'function' is displayed
// Every object inherits a 'constructor' property from its prototype, which points to the constructor function that has created the object:
window.alert(my_function.constructor === Function); // 'true' is displayed

Arguments' default values

Rule(s)
Example
// 'Run' as a static function in a class:
static Run(name = "FranckBarbier", job = "Trainer") { …

Anonymous functions

Rule(s)
Example
let f = function (g) { // 'f' is defined
    g();
};
f(function () { // 'f' is called with an anonymous function as parameter
    window.alert("This no-name function plays the role of 'g' as parameter of 'f'");
});

Lambda expressions (and some JavaScript 6 stuff)

Rule(s)
Example
let f = (g, i = 0) => { // 'f' is defined by means of a lambda expression
    window.alert(g(i));
};
// Calling f...
f(function (my_i) { // 'f' is called with an anonymous function as parameter
    return ++my_i;
}/*, 1*/);
// Calling f, another style...
f(my_i => { // 'f' is called with an arrow as parameter
    return ++my_i;
}/*, 1*/);
// Calling f, yet another style...
f(my_i => ++my_i/*, 1*/); // Implicit 'return'

Variable number of arguments

Rule(s)
Example
let h = function (a = -1, ...bs /*, c*/ /* <- error! */) {
    let sum = a;
    bs.forEach(b => {
        sum += b;
    });
    window.alert("Sum: " + sum);
};
// Note that default value for 'a' is useless:
h(1, 2, 3); // 'Sum: 6' is displayed, i.e., '1' is substituted for 'a'
h(...[1, 2, 3]); // <=> 'h(1, 2, 3);'

Meta-functions

Rule(s)
Example
let my_function = function (my_parameter) {
    window.alert(this.surname); // 'Barbier' is displayed since 'Franck' is substituted for 'this' below
    return ++my_parameter;
};
// This is equivalent to 'my_function(0)' above, but the call is more sophisticated:
window.alert("call: " + my_function.call(Franck, 0)); // First arg. plays the role of 'this' inside the function while '0' is substituted for 'my_parameter'
window.alert("apply: " + my_function.apply(Franck, [0])); // First arg. plays the role of 'this' inside the function while '[0]' is a one-element array containing '0' as unique element
Resource(s)

Generator functions

Rule(s)
Example (Generator.js.zip )
 "use strict";
let meal = {when: "today", taste: "medium"};

let {when: first_part, ...remaining_part} = meal;

// window.alert(first_part); // 'today'
// window.alert(JSON.stringify(remaining_part)); // '{"taste":"medium"}'

meal[Symbol.iterator] = function* (from = "yesterday") { // Key 'Symbol.iterator' (i.e., '@@iterator') is added as 'Generator' object
    yield from;
    yield "today";
    yield "tomorrow";
};
// window.alert(Object.getOwnPropertySymbols(meal)[0] === Symbol.iterator); // 'true'

let iterator = meal[Symbol.iterator]();
// window.alert(iterator.next().value); // 'yesterday'

// Spread syntax only applies on iterable objects:
window.alert([...meal]); // 'yesterday,today,tomorrow'

for (let value of meal) {
    console.log(value); // 'yesterday' 'today' 'tomorrow'
}
As in Java or C++, JavaScript supports exceptions.
Rule(s)
Example (Temperature.js.zip )
try {
    var t1 = new Temperature(-1, Temperature_unit.Kelvin);
} catch (ite) {
    window.alert(ite._message + ": physics' laws prevent -1°K...");
    throw ite; // This means that the execution context has no way of correcting the defect...
} finally {
    window.alert("'finally' as in Java...");
}
Although JavaScript 5 is not a OO programming language, OO principles may apply through a disciplined design.
Rule(s)
Example (old fashion)
var temperature = { // The notion of temperature
    Min: -273.15, // in Celsius
    _value: 0, // in Celsius
    _step: 0.0001,
    asCelsius: function () {
        return this._value;
    }
    // Etc.
};
Example (JavaScript 6 alternate syntax)
var temperature = { // The notion of temperature
    Min: -273.15, // in Celsius
    _value: 0, // in Celsius
    _step: 0.0001,
    asCelsius() { // Not so clear because confusing with a call of 'asCelsius'...
        return this._value;
    }
    // Etc.
};
Rule(s)
Example (better, but still not up-to-date)
var Temperature_unit = {
    Celsius: 0,
    Fahrenheit: 1,
    Kelvin: 2
};

var Invalid_temperature_exception = function (value) { // Exception type
    this._message = "Invalid temperature";
    this._value = value;
};

var Temperature = function (value, unit) {
    this.Min = -273.15; // in Celsius
    this._value = 0; // in Celsius
    switch (unit) {
        case Temperature_unit.Celsius:
            this._value = value;
            break;
        case Temperature_unit.Fahrenheit:
            this._value = (value - 32.) * 5. / 9.;
            break;
        case Temperature_unit.Kelvin:
            this._value = value + this.Min;
            break;
        default:
            throw "Illegal temperature unit";
    }
    if (this._value < this.Min) {
        throw new Invalid_temperature_exception(this._value);
    }
    this._step = 0.0001;
    this.asCelsius = function () {
        return this._value;
    };
    this.asFahrenheit = function () {
        return 9. / 5. * this._value + 32.;
    };
// Better:
    Object.defineProperty(this, "asKelvin", {value: function () {
                return this._value - this.Min;
            }, enumerable: true, configurable: false, writable: false}
    );
    // Etc.     
};
Example (general approach)
var My_type = function (my_attribute) {
    this.my_attribute = my_attribute;
    this.getAttribute = () => {
        return this.my_attribute;
    };
    this.setAttribute = (my_attribute) => {
        this.my_attribute = my_attribute;
    };
}; 

const mt = new My_type("A given instance of 'My_type'...");
window.alert(mt.getAttribute()); // 'A given instance of 'My_type'...' is displayed
window.console.assert(mt.constructor === My_type);
window.console.assert(Object.getPrototypeOf(mt) === My_type.prototype); // "Prototype inheritance"...
window.alert(My_type.prototype.constructor); // Source code is displayed
window.console.assert(My_type.prototype.constructor.name === "My_type");
Rule(s)
Example
Object.defineProperty(Temperature.prototype, "Min", {value: -273.15, enumerable: true, configurable: false, writable: false});

Temperature.prototype.asCelsius = function () {
    return this._value;
};

Temperature.prototype.asFahrenheit = function () {
    return 9. / 5. * this._value + 32.;
};

// Better:
Object.defineProperty(Temperature.prototype, "asKelvin", {value: function () {
        return this._value - this.Min;
    }, enumerable: true, configurable: false, writable: false}
);

// Etc.
Rule(s)
Example
var Pair = (first, second) => {
    this.first = first;
    this.second = second;
};
const p = new Pair('a', 'z'); // Bug: 'TypeError: Pair is not a constructor'
Pair('a', 'z'); // Bug: 'this' is 'undefined'!
Rule(s)
Example
var Pair = function (first, second) {
    this.first = first;
    this.second = second;
};
Pair.prototype.getFirst = () => {
    return this.first;
};
const p = new Pair('a', 'z'); // This works now...
window.alert(p.getFirst()); // Bug: 'this' is 'undefined'!
Resource(s)
Up to JavaScript 5, no native support for inheritance and polymorphism exists. However, Inheritance and polymorphism can be simulated (here…)
Example of inheritance tree (in French)
Rule(s)
Example
var Compte_bancaire = function (id, solde) {
    this._id = id;
    this._solde = solde;
    this._cumul_interets;
};

Compte_bancaire.prototype.id = function () {
    return this._id;
};
Compte_bancaire.prototype.solde = function () {
    return this._solde;
};
Compte_bancaire.prototype.cumul_interets = function () {
    return this._cumul_interets;
};
Compte_bancaire.prototype.mise_a_jour = function (montant) {
    this._solde += montant;
    return this._solde;
};
Compte_bancaire.prototype.taux_interet = function () {
    throw "Undefined function due to abstract nature of 'Compte_bancaire'…";
};
Compte_bancaire.prototype.appliquer_taux_interet = function () {
    this._cumul_interets = this._solde * (1. + (this.taux_interet() / 100.));
};
Compte_bancaire.prototype.compareTo = function (cb) {
    return this._solde > cb._solde ? 1 : this._solde < cb._solde ? -1 : 0;
};

var Compte_cheque = function (id, solde, taux_interet, seuil) {
    Compte_bancaire.call(this, id, solde); // 'super' in Java
    this._taux_interet = taux_interet;
    this._seuil = seuil;
};
Compte_cheque.prototype = Object.create(Compte_bancaire.prototype); // Inheritance link
Compte_cheque.prototype.constructor = Compte_cheque;

Compte_cheque.prototype.taux_interet = function () {
    return this._taux_interet;
};
Compte_cheque.prototype.appliquer_taux_interet = function () {
    if (this._solde > this._seuil) {
        Compte_bancaire.prototype.appliquer_taux_interet.call(this); // 'super' in Java
    }
};
Rule(s)
Example
let cb = null;
try {
    cb = new Compte_bancaire("cb", 100.);
    cb.appliquer_taux_interet(); // This fails since 'Compte_bancaire' is implemented as an abstract class
    window.alert(cb.cumul_interets());
} catch (e) {
    window.alert(e);
}
cb = new Compte_cheque("cc", 200., 0.02, 100.);
cb.appliquer_taux_interet();
window.alert(cb.cumul_interets());
Resource(s)
Inheritance and polymorphism are natively supported from JavaScript 6 (ECMAscript 2015).
Rule(s)
Example (static attribute)
class Temperature {
    static Min = -273.15; // in Celsius
    …
}
Rule(s)
Example
class NoLanguageSettings {
    …
    static Universe_radius = 3000;
    static Half_sphere_geometry = new THREE.SphereBufferGeometry(NoLanguageSettings.Universe_radius / 25, 30, 30, 0, Math.PI);
    static _Initializer = (() => {
        NoLanguageSettings.Half_sphere_geometry.computeBoundingSphere();
    })(); // <- Caution: automatic call...
    …
}
Example (full inheritance hierarchy) Miscellaneous.js.zip 
class Compte_bancaire {
    constructor(id, solde) {
        this._id = id;
        this._solde = solde;
        this._cumul_interets;
    }
    static Information() {
        return "Classe générale des comptes bancaires";
    }
    id() {
        return this._id;
    }
    solde() {
        return this._solde;
    }
    cumul_interets() {
        return this._cumul_interets;
    }
    mise_a_jour(montant) {
        this._solde += montant;
        return this._solde;
    }
    taux_interet() {
        throw "Undefined function due to abstract nature of the class...";
    }
    appliquer_taux_interet() {
        this._cumul_interets = this._solde * (1. + (this.taux_interet() / 100.));
    }
    compareTo(cb) {
        return this._solde > cb._solde ? 1 : this._solde < cb._solde ? -1 : 0;
    }
}

class Compte_cheque extends Compte_bancaire {
    constructor(id, solde, taux_interet, seuil) {
        super(id, solde);
        this._taux_interet = taux_interet;
        this._seuil = seuil;
    }
    static Information() {
        return "Classe des comptes bancaires courants ou \"comptes chèque\" - rémunération à la tête du client !";
    }
    taux_interet() {
        return this._taux_interet;
    }
    appliquer_taux_interet() {
        if (this._solde > this._seuil) {
            super.appliquer_taux_interet();
        }
    }
}
Rule(s)
Example Miscellaneous.js.zip 
window.alert(Compte_bancaire.Information());
let cb = null;
try {
    cb = new Compte_bancaire("cb", 100.);
    cb.appliquer_taux_interet(); // This fails since 'Compte_bancaire' is implemented as an abstract class
    window.alert(cb.cumul_interets());
} catch (e) {
    window.alert(e);
}
window.alert(Compte_cheque.Information());
cb = new Compte_cheque("cc", 200., 0.02, 100.);
cb.appliquer_taux_interet();
window.alert(cb.cumul_interets());
JavaScript has a native introspection support.
Rule(s)
Example
const Get_attributes = (object) => {
    return Object.getOwnPropertyNames(object);
};

const Get_functions = (object) => {
    let functions = [];
    for (let f in object)
        if (typeof object[f] === "function" /*&& object.hasOwnProperty(f)*/) // Inherited functions (with comment) as well...
            functions.push(f);
    return functions;
};

const Display_attributes = (object) => {
    window.alert(Get_attributes(object).join(" - "));
};

const Display_functions = (object) => {
    window.alert(Get_functions(object).join(" - "));
};
Resource(s)
The foundation of JavaScript is its event model. Beyond the basic Event type, a lot of event types are available in JavaScript. Occurrences of events (mouse event occurrences for instance) are (automatically) dispatched by JavaScript for asynchronous processing: events are queued and delivered to handling functions at appropriate moments.
Rule(s)
Example (mouse events)
var My_controller = function (…) { // 'My_controller' class (JavaScript 5 style)
    …
    this._my_canvas = window.document.getElementById("my_canvas");
    …
    this._my_canvas.addEventListener('mousedown', My_controller.prototype.pointerdown.bind(this), false);
    this._my_canvas.addEventListener('mousemove', My_controller.prototype.pointermove.bind(this), false);
    this._my_canvas.addEventListener('mouseover', My_controller.prototype.pointerover.bind(this), false);
    this._my_canvas.addEventListener('mouseup', My_controller.prototype.pointerup.bind(this), false);
    …
};
…
My_controller.prototype.pointerdown = function (mouse_event) {
    mouse_event.preventDefault(); // Default behaviors are canceled
    mouse_event.stopPropagation(); // The event occurrence is processed once and for all
    if (mouse_event.button === 0) { // Mouse left button pressed…
        …
    }
    if (mouse_event.button === 2) { // Mouse right button pressed…
        …
    }        
    …
};
Example (drag&drop events)
var My_controller = function (…) { // 'My_controller' class (JavaScript 5 style)
    this._file_reader = new FileReader();
    this._file_reader.onerror = function (event) {
        throw("this._file_reader.onerror");
    };
    const file_reader_onload = function (event) {
        const image = new Image();
        image.onload = function () {
           // Image has been loaded after drag&drop
        };
        image.src = event.target.result;
    };
    this._file_reader.onload = file_reader_onload.bind(this);
    …
    this._my_canvas = document.getElementById("my_canvas");
    …
    this._my_canvas.addEventListener('drop', this._drop.bind(this), false);
    …
};
…
My_controller.prototype._drop = function (drag_drop_event) {
    drag_drop_event.preventDefault(); // Default behaviors are canceled
    drag_drop_event.stopPropagation(); // The event occurrence is processed once and for all
    if (drag_drop_event.dataTransfer.types && drag_drop_event.dataTransfer.types.length > 0 && drag_drop_event.dataTransfer.types[0].toLowerCase().includes("file"))
        this._file_reader.readAsDataURL(drag_drop_event.dataTransfer.files[0]);
};
Rule(s)
Example (user-defined events)
var Time_management = function (image_name, …) { // 'Time_management' class (JavaScript 5 style)
    …
    // Event handling policy:
    window.addEventListener('Image_is_ready', this._create_3D_object.bind(this, image_name), false);
    window.addEventListener('3D_object_is_ready', function (custom_event) {
        if (custom_event.detail.name !== this._image_name)
            throw("Abnormal situation…");
        …
    }.bind(this), false);
    …
    this._image = new Image();
    this._image.onload = function () {
        // Image loaded:
        window.dispatchEvent(new Event('Image_is_ready'));
    };
    this._image.src = image_name; // Loading image from here…
};
…
Time_management.prototype._create_3D_object = function (name) {
    if (!(this._image !== undefined && this._image !== null && this._image instanceof Image && this._image.complete))
        throw("Abnormal situation…");
    … // 3D object is constructed from 'this._image' as texture
    window.dispatchEvent(new CustomEvent('3D_object_is_ready', {'detail': {name: name}}));
};
…
Resource(s)
Timers are the way of performing periodic and/or repetitive tasks: window.setInterval (cyclic timer) and window.setTimeout (one-shot timer) are ready-to-use facilities for time management.
Example
var Time_management = function (…) { // 'Time_management' class (JavaScript 5 style)
    …
    this._interval_id = null; // 'Time_management' instance attribute
    …
    window.addEventListener('3D_object_is_ready', function () {
        // The timer is launched once the '3D_object_is_ready' event occurrence is received:
        this._interval_id = window.setInterval(this._time_out.bind(this), 5000); // Each 5 sec., the '_time_out' function of the 'Time_management' class is called…
    }.bind(this), false);
    …
};
…
Time_management.prototype._time_out = function () {
    if (…) // Some test
        … // This code is executed each 5 sec. until the timer is cancelled!
    else { // The timer is cancelled:
        window.clearInterval(this._interval_id);
        …
    }
};
Resource(s)
Animation is the ability to register a function, which is called each time the browser repaints frames by means of the window.requestAnimationFrame facility.
Rule(s)
Example
var Time_management = function (…) { // 'Time_management' class (JavaScript 5 style)
    …
    this._animation_id = null; 'Time_management' instance attribute
    …
    // The animation is launched once the '3D_object_is_ready' event occurrence is received:
    window.addEventListener('3D_object_is_ready', function (…) {
        …
        this._animation_id = window.requestAnimationFrame(this._animate_3D_object.bind(this));
    }.bind(this), false);
    …
};

Time_management.prototype._animate_3D_object = function (timestamp) {
    if (timestamp !== undefined) { /* first call: 'timestamp === undefined' */
        // One may handle the elapsed time from the first call to '_animate_3D_object'
    }
    … // This code is executed around 60 times per sec. until the animation is cancelled!
    // A new call is queued (mandatory)
    this._animation_id = window.requestAnimationFrame(this._animate_3D_object.bind(this));
};
…
Time_management.prototype._time_out = function () {
    if (…) // Some test
        … // This code is executed each 5 sec. until the timer is cancelled!
    else { // The animation is cancelled:
        …
        window.cancelAnimationFrame(this._animation_id);
        …
    }
};
Resource(s)
Illustration: JavaScript event model
The concept of promise is the key mechanism for dealing with asynchronicity in JavaScript. The Promise type (i.e., Deferred Object/Promise in jQuery) plays the role of support.
Example
const Firefox = Promise.resolve(window.navigator.userAgent.includes("Firefox"));
Firefox.then(result => {
    if (result)
        window.alert("Firefox");
});

const Chrome = Promise.resolve(window.navigator.userAgent.includes("Chrome"));
Chrome.then(result => {
    if (result)
        window.alert("Chrome");
});
Example
const image = new Image();
const is_image_loaded = new Promise(send => {
    image.onload = () => {
        window.console.assert(image.complete);
        send(image.complete);
    };
});
image.src = "img/Large_image.jpg"; // Image load…

const is_image_loaded_in_less_than_100ms = new Promise((yes, no) => {
    window.setTimeout(() => no(new Error('more than 100ms')), 100); // Change to '1000' afterwards...
});

const who_wins = Promise.race([is_image_loaded, is_image_loaded_in_less_than_100ms]);
who_wins.then(image_complete => window.alert("Image complete: " + image_complete));
who_wins.catch(error => window.alert(error));
Rule(s)
Example (using fetch)
// 'fetch' support at 'http://caniuse.com/#feat=fetch'
Promise.all([Promise.resolve(window.fetch !== undefined), window.DOM_ready, fetch("img/Large_image.jpg").then(function (response) {
        return response.blob();
    })]).then(parameters => {
    if (parameters[0] === true) // 'fetch' is supported by the browser
//    'parameters[1]' -> DOM is ready with access to 'image_tag'
//    'parameters[2]' -> Image is available (i.e., 'complete') and transformed into blob
        parameters[1].src = URL.createObjectURL(parameters[2]); // 'image_tag' is loaded from "img/Large_image.jpg"
});
Resource(s)
async and await are “sugar” mechanisms that aim at using promises in a pretty different way.
Rule(s)
Example (Puppeteer.Node.js.zip )
/* Node.js program */

// 'puppeteer.js' library: https://developers.google.com/web/tools/puppeteer/
const puppeteer = require('puppeteer'); // 'npm install --save puppeteer' or 'sudo npm install --save puppeteer'
// Recent download problems require this: 'sudo npm install puppeteer --unsafe-perm=true --allow-root'

// Check whether 'puppeteer.js' has been installed: 'npm list -depth=0'

const take_picture = async () => { // 'async' returns an 'AsyncFunction' object
    /* Key rule:
     * 'await' returns the promise result, say what is computed by 'puppeteer.launch'
     * *NOT USING* 'await' leads to get the promise itself:
     */
//    const call_without_await = puppeteer.launch(); // Bad idea...
//    console.log(call_without_await instanceof Promise); // 'true' is displayed!
    const browser = await puppeteer.launch(/*{executablePath: '/Application/Google\ Chrome.app/Contents/MacOS'}*/); // Launch 'Chrome' without visual environment
    // Following call *DOES NOT* occur (because of prior 'await') until prior one terminates:
    const page = await browser.newPage();
    await page.goto('https://www.google.com/search?tbm=isch&q=nutella');//
    await page.screenshot({path: './Nutella.png'}); // Photo may be found in directory execution context
    await browser.close();
    return 'Nutella.png'; // Photo file name
};

// take_picture(); // Common style of calling a function...

take_picture().then((photo_file_name) => {
    console.log('Photo file name: ' + photo_file_name);
});
Web services are server-side programs accessible throughout the Web. By appropriate calls in JavaScript, one is able to get any data and to reduce computations on the client side.
Rule(s)
Example

Get

const request = new XMLHttpRequest();
request.onreadystatechange = function () {
    window.console.log(request.getAllResponseHeaders());
    if (request.readyState === XMLHttpRequest.DONE) {
        if (request.getResponseHeader("Content-Type").includes("application/json")) {
            const response = JSON.parse(request.responseText);
            window.alert("For 1 US Dollar (USD) to MAD (Moroccan Dirham): " + response.rates.MAD);
        }
    }
};
 // This Web site requires a license key:
request.open("GET", "http://openexchangerates.org/api/latest.json" + "?app_id=" + "<your license key here>", true);
// 'request' must already be opened:
request.send(null);

Post

const request2 = new XMLHttpRequest(); // Stuck by CORS
request2.onreadystatechange = function () {
    if (request2.readyState === XMLHttpRequest.DONE) {
        window.alert(request2.responseText);
    }
};
request2.open("POST", "http://www.w3schools.com" + "/xml/tempconvert.asmx/CelsiusToFahrenheit", true);
// request2.setRequestHeader("Content-Length", 10); // The number of bytes of data in the body of the request or response
request2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // As a HTML form
request2.send("Celsius=20");

Simple Object Access Protocol (SOAP)

const request3 = new XMLHttpRequest(); // Stuck by CORS
request3.onreadystatechange = function () {
    if (request3.readyState === XMLHttpRequest.DONE) {
        // Process response as XML text…
    }
};
request3.open("POST", "http://www.webservicex.net/ConvertTemperature.asmx/ConvertTemp", true);
request3.setRequestHeader("Content-Type", "application/soap+xml");
const content =
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
            "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">" +
            "  <soap12:Body>" +
            "   <ConvertTemp xmlns=\"http://www.webservicex.net/\">" +
            "     <Temperature>18</Temperature>" +
            "     <FromUnit>degreeCelsius</FromUnit>" +
            "     <ToUnit>degreeFahrenheit</ToUnit>" +
            "   </ConvertTemp>" +
            " </soap12:Body>" +
            "</soap12:Envelope>";
request3.send(content);

fetch (Post)

class ReqRes {
    static URL() { return 'https://reqres.in'; }
    static Path() { return '/api/users'; }
    static Run1(name = "FranckBarbier", job = "Trainer") {
        fetch(ReqRes.URL() + ReqRes.Path(), {
            body: JSON.stringify({
                name: name,
                job: job
            }),
            headers: {// Mandatory to get 'result' in appropriate shape...
                'accept': 'application/json', // -> response
                'content-type': 'application/json; charset=UTF-8'
            },
            method: 'POST'
        }).then(response => {
            response.json().then(result => {
                window.console.assert(result.name === name); // 'Req-Res' just returns data for "simulation"...
                window.alert("'ReqRes' ('fetch') RUN1: " + JSON.stringify(result));
            });
        });
    }
…
Note(s)
Resource(s)
WebSockets is a technology that promotes bi-directional full-duplex communication between (not exclusively) browsers and WebSockets servers (example here…). The general way of dealing with WebSockets in JavaScript is described here
Example
let my_WebSocket = new WebSocket("ws:127.0.0.1:8080", "FranckBarbier");
my_WebSocket.onmessage = (event) => {
    let message_data_as_object = JSON.parse(event.data);
    …
};
my_WebSocket.onopen = () => {
    my_WebSocket.send(JSON.stringify({Response: "Handshaking"}));
};
my_WebSocket.onclose = () => {
    // …
};
my_WebSocket.onerror = () => {
    // …
};
Resource(s)
Web Workers is a support for dealing with a kind of multithreading. More precisely, some JavaScript code may run outside the browser so that this code lightens the load on the browser. Web Workers mainly consist in facilities to assign background tasks from a browser to a given Web worker that runs in parallel with the said browser.
Rule(s)
Example (“main” thread in the browser Web_Workers.js.zip )
/*
 * Web_Workers_main.js
 */

"use strict";

function main() {
// jQuery is used:
    var $canvas = $("#My_canvas").get(0); // jQuery access to DOM canvas elem. with 'My_canvas' as id.
    var image = new Image();
    var worker = new Worker("js/Web_Workers_parallel.js"); // Behind the browser stage, this "parallel" code is that of the worker…

    worker.addEventListener("message", response_from_process_image_by_worker); // Subscription about worker's response
    function response_from_process_image_by_worker(message) { // Handler of worker's response
        swal({// Use of the nice 'sweetalert' JS library!
            title: "Web Workers",
            text: "Worker just terminated image processing… Show it?",
            type: "warning",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes!",
            closeOnConfirm: true
        }, function () {
            $canvas.getContext('2d').putImageData(message.data, 0, 0); // Reload of processed image…
        });
        worker.terminate(); // Worker is no longer used, 'close' optional statement
    }

    $(document).on("go!", process_image_by_worker); // Wait for image availability
    function process_image_by_worker() { // Handler of image availability
        if (window.Worker) { // Test if the browser supports the Web Workers technology
            // Instance of 'ImageData' must be sent since it is processable by the new HTML5 structured clone algorithm:
            worker.postMessage($canvas.getContext('2d').getImageData(0, 0, $canvas.width, $canvas.height));
        }
    }

    image.onload = function () {
        $canvas.width = image.width;
        $canvas.height = image.height;
        $canvas.getContext('2d').drawImage(image, 0, 0); // Image is loaded in canvas
        $(document).trigger("go!"); // Image availability: event triggering in jQuery
    };
    image.src = "img/Image.jpg"; // Image load…
}
Example (“parallel” thread outside the browser Web_Workers.js.zip )
/*
 * Web_Workers_parallel.js
 */

"use strict";

self.importScripts("chai.js"); // Reused libraries require local-scope load…

function process(image_data) {
    var buffer = new Uint32Array(image_data.data.buffer);
    for (var pixel_number = 0; pixel_number < buffer.length; pixel_number++) {
        var alpha = buffer[pixel_number] >>> 24; // Most left byte
        var blue = (buffer[pixel_number] & 0x00FF0000) >> 16;
        var green = (buffer[pixel_number] & 0x0000FF00) >> 8;
        var red = buffer[pixel_number] & 0x000000FF; // Most right byte
// Simplistic image processing, please improve:
        blue = ~blue;
        green = ~green;
        // red = ~red;
        buffer[pixel_number] = (alpha << 24) | (blue << 16) | (green << 8) | red;
    }
}

onmessage = function (message) { // Message from 'main' thread, i.e., 'worker.postMessage($canvas.getContext('2d').getImageData(0, 0, $canvas.width, $canvas.height));', is received…
    chai.assert.isTrue(message.data instanceof ImageData); // Check received data
    process(message.data);
    postMessage(message.data); // Response from worker to 'main' thread…
};
JavaScript supports rich APIs for multimedia management (image, video, sound…) in general and gaming in particular.
Full screen is simply the ability to use the machine's full screen and vice versa when leaving the full screen mode. The full screen API still stumbles over incompatible browser behaviors, requiring the FullScreen object for activations/desactivations.
Example
var FullScreen = FullScreen || {};
FullScreen.available = function () { // Are full screen capabilities available?
    return this._hasWebkitFullScreen || this._hasMozFullScreen;
};

FullScreen.activated = function () { // Test if full screen is currently activated…
    if (this._hasWebkitFullScreen) {
        return document.webkitIsFullScreen;
    } else if (this._hasMozFullScreen) {
        return document.mozFullScreen;
    } else {
        window.console.assert(false);
    }
};

FullScreen.request = function (element) { // Request full screen on a given element…
    element = element || document.body;
    if (this._hasWebkitFullScreen) {
        element.webkitRequestFullScreen();
    } else if (this._hasMozFullScreen) {
        element.mozRequestFullScreen();
    } else {
        window.console.assert(false);
    }
};

FullScreen.cancel = function () { // Cancel full screen…
    if (this._hasWebkitFullScreen) {
        document.webkitCancelFullScreen();
    } else if (this._hasMozFullScreen) {
        document.mozCancelFullScreen();
    } else {
        window.console.assert(false);
    }
};

// Internal functions to know which full screen API implementation is available
FullScreen._hasWebkitFullScreen = 'webkitCancelFullScreen' in document ? true : false;
FullScreen._hasMozFullScreen = 'mozCancelFullScreen' in document ? true : false;
In a standardization logic, JavaScript lets access to device equipment with presence testing capability. Typically, the Vibration API may enact the vibrator, if any, in a software manner.
Example (Vibration_API.js.zip )
window.addEventListener("DOMContentLoaded", () => { // DOM just loaded...
    window.console.assert(window.document.readyState !== "loading");

    const FB = window.document.getElementById("FB");

    let angle = 10;
    const interval_id = window.setInterval(() => {
        FB.style.transform = "rotate(" + angle + "deg)";
        angle = -angle;
        window.navigator.vibrate(50);
    }, 100);

    FB.addEventListener("click", () => {
        window.clearInterval(interval_id);
        window.document.getElementById("Feel_it_").innerHTML = "Vibration just stops...";
    });
});
In a smartphone-based logic, JavaScript supports accelerometer and/or gyroscope measures for device motion and device orientation. The devicemotion and deviceorientation events are devoted to this task.
Example (Google_cardboard_three_js.zip )
window.addEventListener('deviceorientation', event => {
    data.innerHTML = "'z' motion (0/360): " + event.alpha + "
"; data.innerHTML += "'x' motion (-180/180): " + event.beta + "
"; data.innerHTML += "'y' motion (-90/90): " + event.gamma; }); // Three.js support: const device_orientation_controls = new THREE.DeviceOrientationControls(camera, true); device_orientation_controls.connect(); … device_orientation_controls.update(); // Animation loop...
WebRTC standing for Web Real-Time Communications allows the direct access to input device, namely webcams and microphones.
Rule(s)
Example (finding available devices)
// A promise is returned:
window.navigator.mediaDevices.enumerateDevices().then(function (devices) { // 'window.navigator.mediaDevices !== undefined' -> WebRTC available!
    devices.forEach(function (device) {
        window.alert(device.kind + ": " + device.label + " id = " + device.deviceId);
    });
})
.catch(function (error) {
    window.console.log(error.name + ": " + error.message);
});
Rule(s)
Example (Selfie.js.zip )
<video id="my_video" width="200" height="300" poster="./img/FranckBarbier.jpg"></video>
DOM_ready.then(value => { // DOM is ready as a promise...
    /* Webcam shooting **/
    // Tested with Chrome >= 68, Firefox >= 62, Edge >= 42, and Safari >= 11
    let _my_video = document.getElementById('my_video');
    _my_video.addEventListener('canplay', () => {
        window.console.log("The video is playing...");
        window.console.log("_my_video.videoHeight: " + _my_video.videoHeight + " _my_video.videoWidth: " + _my_video.videoWidth);
    });
    let _working_canvas = window.document.createElement('canvas');

// window.alert("typeof navigator.mediaDevices.getUserMedia: " + typeof navigator.mediaDevices.getUserMedia); // 'function'
// window.alert("Is Promise? " + (navigator.mediaDevices.getUserMedia({audio: false, video: true}) instanceof Promise)); // 'true'
// Safari : voir aussi onglet "Développement", option WebRTC
    /* Non supporté par Safari : {video: {width: 512, height: 512, facingMode: "user"}} */
// Looking at device capabilities:
// window.alert(JSON.stringify(navigator.mediaDevices.getSupportedConstraints()));

    let constraints = {audio: false, video: true};
    if (window.navigator.mediaDevices.getSupportedConstraints().hasOwnProperty('facingMode'))
        constraints = {audio: false, video: {facingMode: 'user'}}; // Selfie mode 

    let _video_management = () => {
        if (_my_video.srcObject !== null) {
            if (_my_video.srcObject.getVideoTracks()[0].readyState === "live") { // Video is running, take photo...
                Snapshot.then(sound => {
                    sound.play();
                });
                // Before stopping the camera, one records the last frame:
                _working_canvas.setAttribute('width', _my_video.videoWidth);
                _working_canvas.setAttribute('height', _my_video.videoHeight);
                _working_canvas.getContext('2d').drawImage(_my_video, 0, 0, _my_video.videoWidth, _my_video.videoHeight);
                let _selfie = new Image();
                _selfie.onload = function () {
                    // This immediately stops the webcam (Firefox keeps the last frame on screen while Chrome generates a black screen):
                    _my_video.srcObject.getVideoTracks()[0].stop();
                    // The stream is no longer active:
                    window.console.assert(_my_video.srcObject.active === false);
                    window.console.assert(_my_video.srcObject.getVideoTracks()[0].readyState === "ended");
                    // The stream is detached from the '<video>' tag:
                    _my_video.srcObject = null; // For next shoot...
                    _my_video.setAttribute('poster', _selfie.src);
                };
                _selfie.src = _working_canvas.toDataURL("image/png"); // From canvas to image...
            } else
                window.alert("_my_video.srcObject.getVideoTracks()[0].readyState === \"ended\"");
        } else { // *New* stream is *required* for additional shoots!
            // Firefox asks for permission again...
            window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
                // Safari issue: running video does not appear inside browser (from second round) while we're really filmed! Worse still, shooting works!
                // Issue not solved despite this:
                // https://help.milkshake.tv/hc/en-us/articles/115005464689-Videos-not-playing-when-using-Safari-11-web-browser
                _my_video.srcObject = stream; // Assign the webcam to the "my_video" HTML element
                _my_video.play(); // Start playing video...
            }).catch((error) => {
                window.alert("navigator.mediaDevices.getUserMedia: " + error.message);
            });
        }
    };

    if (window.PointerEvent) // May not work for some browsers...
        _my_video.onpointerup = _video_management;
    else // Safari does not yet support 'window.PointerEvent' (https://caniuse.com/#feat=pointer):
        _my_video.addEventListener('mouseup', _video_management, true);
});
/** End of DOM ready */
The Web Audio API benefits from being used through high-end devoted libraries, notably SOUNDJS.
Example (Theo_is_crying.js.zip )
createjs.Sound.on("fileload", event => { // This is fired for each sound that is registered...
 // 'PlayPropsConfig' class of SOUNDJS API:
    const instance = createjs.Sound.play(event.id, {interrupt: createjs.Sound.INTERRUPT_ANY, loop: 1, volume: 0.5, duration: 500});
    instance.on("complete", () => {
        window.console.log("End of: " + event.id);
    });
});
createjs.Sound.registerSound("./sounds/Baby_laughing.mp3", "Baby_laughing_sound_ID");
…
createjs.Sound.registerSound("./sounds/Baby_crying.mp3", "Baby_crying_sound_ID");
…
const result = createjs.Sound.play("Baby_crying_sound_ID"); // Potential bug: the sound may not yet be loaded...
if (result.playState !== createjs.Sound.PLAY_SUCCEEDED)
    window.console.warn(result.src + ": " + result.playState);
       
The Speech synthesis mainly works with Chrome, intro. here….
The Speech recognition mainly works with Chrome, intro. here….