Intro


    // variables list
    var one_1, _2, $_3;
    /*
    * variables definition
    */
    one_1 = 1;
    _2 = 2.02;
    $_3 = one_1 + _2;

    var nr_4 = "four";

    var fifth = 5.55, sixth = 6.98;

    var seven = 7.77,
        eight = 8.0937895;

    var x = "5" + 2 + 3; // 523
    var x = 2 + 3 + "5"; // 55

    // addition and concatenation
    var x = 5 + 7;       // x.valueOf() is 12,  typeof x is a number
    var x = 5 + "7";     // x.valueOf() is 57,  typeof x is a string
    var x = "5" + 7;     // x.valueOf() is 57,  typeof x is a string
    var x = 5 - 7;       // x.valueOf() is -2,  typeof x is a number
    var x = 5 - "7";     // x.valueOf() is -2,  typeof x is a number
    var x = "5" - 7;     // x.valueOf() is -2,  typeof x is a number
    var x = 5 - "x";     // x.valueOf() is NaN, typeof x is a number

    // completing statements
    function myFunction(a) {
      var
      power = 10; // var was assigned, JS tried to complete var definition
      return      // will return undefined from this function, return - is a complete statement
      a * power;
    }

    // see "Scope,var,let,const" article for extensive information about variables definition
  

AVOID


    // complicates your code and slow down execution speed
    var x = new String();        // Declares x as a String object
    var y = new Number();        // Declares y as a Number object
    var z = new Boolean();       // Declares z as a Boolean object

    var x = 0;
    var y = "10";
    if (x == 10) // false
    if (x = 10) // true
    if (x = 0) // false
    if (x == y) // true
    if (x === y) // false
    switch(x) { case 10: alert("Hello"); } // works - types are the same
    switch(x) { case "10": alert("Hello"); } // types are different

    for (var i = 0; i < 10; i++) {
      // some code
    }
    return i; // 10
  

DO


    // Declare at the beginning
    var firstName, lastName, price, discount, fullPrice, i;

    var firstName = "",
      lastName = "",
      price = 0,
      discount = 0,
      fullPrice = 0,
      myArray = [],
      arr_length = myArray.length,
      myObject = {};

    // Use later
    firstName = "John";
    lastName = "Doe";
    price = 19.90;
    discount = 0.10;
    fullPrice = price * 100 / discount;
    for (i = 0; i < arr_length; i++) { ... }

    var x1 = {};           // new object
    var x2 = "";           // new primitive string
    var x3 = 0;            // new primitive number
    var x4 = false;        // new primitive boolean
    var x5 = [];           // new array object
    var x6 = /()/;         // new regexp object
    var x7 = function(){}; // new function object

    function myFunction(x, y) {
      if (y === undefined) { y = 0; }
      //...
    }

  

Boolean


    Boolean(10 > 9)        // returns true
    (10 > 9)              // also returns true
    10 > 9                // also returns true

    // Everything With a "Value" is True
    100
    3.14
    -15
    "Hello"
    "false"
    7 + 1 + 3.14

    // Everything Without a "Value" is False
    0
    -0
    ""
    undefined
    null
    false
    NaN

    String(false)        // returns "false"
    String(true)         // returns "true"
    false.toString()     // returns "false"
    true.toString()      // returns "true"

    // !! - is not an operator, it's just the ! operator twice
    console.log(navigator.userAgent.match(/MSIE 8.0/)); // null
    console.log(!!navigator.userAgent.match(/MSIE 8.0/)); // returns true or false
  

Strings


    var carname = "Volvo XC60";  // Double quotes
    var carname = 'Volvo XC60';  // Single quotes
    var answer = "It's alright";
    var answer = "He is called 'Johnny'";
    var answer = 'He is called "Johnny"';

    // escaping special characters
    var x = "We are the so-called \"Vikings\" from the north.";
    var x = 'It\'s alright.';
    var x = "The character \\ is called backslash.";

    // breaking lines
    document.getElementById("demo").innerHTML =
    "Hello Andrei!";
    document.getElementById("demo").innerHTML = "Hello " +
    "Andrei!";
  

METHODS


    // LENGTH
    var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var sln = txt.length;

    // indexOf() and search() are NOT equal
    // - search() method cannot take a second start position argument
    // - indexOf() method cannot take powerful search values (regular expressions)

    // FIND
    // --- indexOf, lastIndexOf
    // both indexOf(), and lastIndexOf() return -1 if the text is not found
    // both methods accept a second parameter as the starting position for the search
    var str = "Please locate where 'locate' occurs!";
    var pos = str.indexOf("locate"); // position of the first occurrence
    var pos = str.lastIndexOf("locate"); // position of the last occurrence
    var pos = str.indexOf("locate",15);

    // --- search
    var pos = str.search("locate"); // returns the position of the match

    // --- replace
    str = "Please visit Microsoft and Microsoft!";
    var n = str.replace("Microsoft", "W3Schools"); // case-sensitive replacement
    var n = str.replace(/MICROSOFT/i, "W3Schools"); // case-insensitive replacement
    var n = str.replace(/Microsoft/g, "W3Schools"); // replace all matches

    // --- match - of a string inside other string
    var res = str.match(/Microsoft/gi); // ['Microsoft','Microsoft']
    // --- matchAll() (ES2020) - returns an iterator of all results matching a string against a regular expression, including capturing groups
    const regexp = /t(e)(st(\d?))/g;
    const str = 'test1test2';
    const array = [...str.matchAll(regexp)];
    console.log(array[0]); // ["test1", "e", "st1", "1"]
    console.log(array[1]); // ["test2", "e", "st2", "2"]

    // EXTRACT
    var str = "Apple, Banana, Kiwi";
    // --- slice(start_pos [,end_pos] )
    var res = str.slice(7, 13); // Banana
    var res = str.slice(-12, -6); // Banana - with negative(from end) offsets
    var res = str.slice(7); // Banana, Kiwi
    var res = str.slice(-12); // Banana, Kiwi - with negative(from end) offsets
    // --- substring(start_pos [,end_pos] )
    // similar to slice but dont accept negative indexes
    var res = str.substring(7, 13);  // Banana
    var res = str.substring(7); // Banana, Kiwi
    // --- substring(start_pos [,length] )
    var res = str.substr(7, 6);  // Banana
    var res = str.substr(7); // Banana, Kiwi

    // CASE CONVERSION
    var text1 = "Hello World!";
    var text2 = text1.toUpperCase();  // to upper case
    var text2 = text1.toLowerCase();  // to lower case

    // JOIN STRINGS
    var text = "Hello".concat(" ", "World!"); // same as "Hello" + " " + "World!"
    var text1 = "Hello";
    var text2 = "World";
    var text3 = text1.concat(" ", text2);
    var text = text1.concat(" ", "World", " ", "!");

    // TRIM
    var str = "       Hello World!        ";
    alert(str.trim()); // "Hello World!"

    // EXTRACT CHARACTER
    var str = "HELLO WORLD";
    str.charAt(0);  // returns H as character at position 0
    str.charCodeAt(0); // returns 72 unicode of the character at position 0
    str[0]; // returns H
    // if no character is found, [ ] returns undefined, while charAt() returns an empty string

    // CONVERT TO ARRAY
    var txt = "a,b c,d|e,f g,h";   // String
    txt.split(",");          // Split on commas
    txt.split(" ");          // Split on spaces
    txt.split("|");          // Split on pipe
    txt.split("");           // Split in characters

    // convert a set of Unicode values into characters
    var res = String.fromCharCode(72, 69, 76, 76, 79);

    // RANDOM STRING
    Math.random().toString(36).slice(2)
    // EXTRACT DOMAIN NAME
    let email = 'xyz@gmail.com';
    email.substring(email.indexOf('@') + 1); // output - gmail.com
  

ES2015


    // Template Literals
    // 'Your name is ' + first + ' ' + last + '.'
    var name = `Your name is ${first} ${last}.`
    // 'http://localhost:3000/api/messages/' + id
    var url = `http://localhost:3000/api/messages/${id}`

    // multi-line string
    var test = `<body>
      <article>
        <time datetime='${ precalculatedIso }'>${ precalculatedIso }</time>
      </article>
      <div>Hobbies:</div>
      <ul>
        ${hobbies.map(hobby => `<li>${hobby}</li>`).join(" ")}
      </ul>
    </body>`;

    // function call ( avoid () )
    let name = "Andrei", age = "32";
    parseStr`My name is ${name}, and I'm ${age} years old`;
    function parseStr(templates, name, age){
      // raw - special property, allows to access the raw strings
      console.log('Template: ', templates); // [“My name is”, “, and I'm “, “ years old”, raw:[...]]
      console.log('Param 1: ', name); // Andrei
      console.log('Param 2: ', age); // 32
    }
    // func([“My name is”, “, and I'm “, “ years old”], <value of name>, <value of age>);

    // Construct an HTTP request prefix is used to interpret the replacements and construction
    GET`http://foo.org/bar?a=${a}&b=${b}
        Content-Type: application/json
        X-Credentials: ${credentials}
        { "foo": ${foo},
        "bar": ${bar}}`(myOnReadyStateChangeHandler);

    var str = "Hello world, welcome to the universe.";
    // str.startsWith(search_val [,start_pos]) = true/false
    str.startsWith("world", 6);
    if (!String.prototype.startsWith) {
      Object.defineProperty(String.prototype, 'startsWith', {
        value: function(search, pos) {
          return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
        }
      });
    }
    // str.endsWith(search_val [,length]) = true/false
    str.endsWith("universe.");
    if (!String.prototype.endsWith) {
      String.prototype.endsWith = function(search, this_len) {
        if (this_len === undefined || this_len > this.length) {
          this_len = this.length;
        }
        return this.substring(this_len - search.length, this_len) === search;
      };
    }
    // str.repeat( count ) = repeat string
    str.repeat(2);
    if (!String.prototype.repeat) {
      String.prototype.repeat = function(count) {
        'use strict';
        if (this == null) {
          throw new TypeError('can\'t convert ' + this + ' to object');
        }
        var str = '' + this;
        count = +count;
        if (count != count) {
          count = 0;
        }
        if (count < 0) {
          throw new RangeError('repeat count must be non-negative');
        }
        if (count == Infinity) {
          throw new RangeError('repeat count must be less than infinity');
        }
        count = Math.floor(count);
        if (str.length == 0 || count == 0) {
          return '';
        }
        // Ensuring count is a 31-bit integer allows us to heavily optimize the
        // main part. But anyway, most current (August 2014) browsers can't handle
        // strings 1 << 28 chars or longer, so:
        if (str.length * count >= 1 << 28) {
          throw new RangeError('repeat count must not overflow maximum string size');
        }
        var maxCount = str.length * count;
        count = Math.floor(Math.log(count) / Math.log(2));
        while (count) {
           str += str;
           count--;
        }
        str += str.substring(0, maxCount - str.length);
        return str;
      }
    }
  

ES2016


    // str.includes(search_val [,start_pos]) = true/false
    str.includes("world", 12);
    if (!String.prototype.includes) {
      Object.defineProperty(String.prototype, 'includes', {
        value: function(search, start) {
          if (typeof start !== 'number') {
            start = 0
          }

          if (start + search.length > this.length) {
            return false
          } else {
            return this.indexOf(search, start) !== -1
          }
        }
      })
    }
  

ES2017


    // str.padStart(targetLength [, padString])
    console.log('5'.padStart(2, '0')); // 05
    const last4Digits = '2034399002125581'.slice(-4);
    const maskedNumber = last4Digits.padStart('2034399002125581'.length, '*');
    console.log(maskedNumber); // ************5581
    'abc'.padStart(10);         // "       abc"
    'abc'.padStart(10, "foo");  // "foofoofabc"
    'abc'.padStart(6,"123465"); // "123abc"
    'abc'.padStart(8, "0");     // "00000abc"
    'abc'.padStart(1);          // "abc"

    // str.padEnd(targetLength [, padString])
    'Breaded Mushrooms'.padEnd(25, '.') // Breaded Mushrooms........
    '200'.padEnd(5);          // "200  "
    'abc'.padEnd(10);         // "abc       "
    'abc'.padEnd(10, "foo");  // "abcfoofoof"
    'abc'.padEnd(6, "123456");// "abc123"
    'abc'.padEnd(1);          // "abc"

    if (!String.prototype.padStart) {
      String.prototype.padStart = function padStart(targetLength, padString) {
        // truncate if number, or convert non-number to 0;
        targetLength = targetLength >> 0;
        padString = String(typeof padString !== 'undefined' ? padString : ' ');
        if (this.length >= targetLength) {
          return String(this);
        } else {
          targetLength = targetLength - this.length;
          if (targetLength > padString.length) {
            // append to original to ensure we are longer than needed
            padString += padString.repeat(targetLength / padString.length);
          }
          return padString.slice(0, targetLength) + String(this);
        }
      };
    }
    if (!String.prototype.padEnd) {
      String.prototype.padEnd = function padEnd(targetLength,padString) {
        // floor if number or convert non-number to 0;
        targetLength = targetLength>>0;
        padString = String((typeof padString !== 'undefined' ? padString : ' '));
        if (this.length > targetLength) {
            return String(this);
        }
        else {
          targetLength = targetLength-this.length;
          if (targetLength > padString.length) {
            // append to original to ensure we are longer than needed
            padString += padString.repeat(targetLength/padString.length);
          }
          return String(this) + padString.slice(0,targetLength);
        }
      };
    }
  

ES2018


    // str.trimStart|trimEnd|trimLeft|trimRight()
    '   abc'.trimStart();       // "abc"
    'abc   '.padStartrimEndt(); // "abc"
    '   abc   '.trimEnd().trimStart(); // "abc"
  

ES2019


    // template literal revision - parse a template literal with a function
    function fn(string, substitute) {
      if(substitute === 'ES6') { substitute = 'ES2015' }
      return substitute + string[1];
    }
    const version = 'ES6';
    const result = fn`${version} was a major update`; // ES2015 was a major update
    // represents invalid escape sequences as undefined:
    function fn(string, substitute) {
      console.log(substitute);    // escape sequences:
      console.log(string[1]);     // undefined
    }
    const str = 'escape sequences:';
    const result = fn`${str} \ubuntu C:\xxx\uuu`;
    // using illegal escape sequences in a regular template literal still causes an error:
    const result = `\ubuntu`; // SyntaxError: Invalid Unicode escape sequence
  
Escape sequences
Code Result
\' Single quote
\" Double quote
\\ Backslash
\b Backspace
\f Form Feed
\n New Line
\r Carriage Return
\t Horizontal Tabulator
\v Vertical Tabulator

Numbers


    var x = 3.14;    // A number with decimals
    var y = 3;       // A number without decimals
    var x = 123e5;    // 12300000
    var y = 123e-5;   // 0.00123

    // integers (numbers without a period or exponent notation) are accurate up to 15 digits
    var x = 999999999999999;   // x will be 999999999999999
    var y = 9999999999999999;  // y will be 10000000000000000

    // maximum number of decimals is 17, but floating point arithmetic is not always 100% accurate
    var x = 0.2 + 0.1;         // x will be 0.30000000000000004
    // to solve the problem above, it helps to multiply and divide
    var x = (0.2 * 10 + 0.1 * 10) / 10;       // x will be 0.3

    // JavaScript will try to convert strings to numbers in all numeric operations
    // except concatenation (+)
    var x = "100";
    var y = "10";
    var z = x / y;       // z will be 10
    var z = x * y;       // z will be 1000
    var z = x - y;       // z will be 90
    var z = x + y;       // z will not be 110 (It will be 10010) !

    // NaN - Not a Number
    var x = 100 / "Apple";  // x will be NaN (Not a Number)
    var z = NaN + 7;        // z will be NaN
    var x = 100 / "Apple";
    isNaN(x);               // ES2015 - returns true because x is Not a Number
    typeof NaN;            // returns "number"

    // Infinity
    var myNumber = 2;
    while (myNumber != Infinity) {
      myNumber = myNumber * myNumber;
    }
    // myNumber will be :
    // 4
    // 16
    // 256
    // 65536
    // 4294967296
    // 18446744073709552000
    // 3.402823669209385e+38
    // 1.157920892373162e+77
    // 1.3407807929942597e+154
    var x =  2 / 0;          // x will be Infinity
    var y = -2 / 0;          // y will be -Infinity
    typeof Infinity;        // returns "number"

    // binary (0b)
    0b111110111 === 503
    // octal (0o)
    0o767 === 503
    // Hexadecimal (0x)
    0xFF === 255
  

STATIC PROPERTIES


    // can only use it as Number.*
    Number.MAX_VALUE; // 1.7976931348623157e+308 , larger numbers are represented as infinity
    Number.MIN_VALUE; // the value closest to 0 , 5e-324 , smaller numbers are converted to 0
    Number.NEGATIVE_INFINITY; // -Infinity
    Number.POSITIVE_INFINITY; // Infinity , returned on overflow
    Number.NaN;
  

STATIC METHODS


    parseInt("10");         // returns 10
    parseInt("10.33");      // returns 10
    parseInt("10 20 30");   // returns 10
    parseInt("10 years");   // returns 10
    parseInt("years 10");   // returns NaN

    parseFloat("10");        // returns 10
    parseFloat("10.33");     // returns 10.33
    parseFloat("10 20 30");  // returns 10
    parseFloat("10 years");  // returns 10
    parseFloat("years 10");  // returns NaN

    // by default, JavaScript displays numbers as base 10 decimals
    var num = 32;
    num.toString(10);   // returns 32
    num.toString(32);  // returns 10
    num.toString(16);  // returns 20
    num.toString(8);   // returns 40
    num.toString(2);   // returns 100000

    // CONVERTING variables to Numbers
    Number(true);          // returns 1
    Number(false);         // returns 0
    Number("10");          // returns 10
    Number("  10");        // returns 10
    Number("10  ");        // returns 10
    Number(" 10  ");       // returns 10
    Number("10.33");       // returns 10.33
    Number("10,33");       // returns NaN
    Number("10 33");       // returns NaN
    Number("John");        // returns NaN

    Number(new Date("2017-09-30"));    // 1506729600000 - number of milliseconds since 1.1.1970

    var num = 59753657.56789;
    num.toExponential(); // 5.975365756789e+7 , exponential version

    // toFixed - converts number to string, keeping a specified number of decimals
    // perfect for working with money
    var num = 9.656;
    num.toFixed(0);           // returns 10
    num.toFixed(2);           // returns 9.66
    num.toFixed(4);           // returns 9.6560
    num.toFixed(6);           // returns 9.656000

    //format number to a specified length
    var num = 13.3714;
    num.toPrecision(); // 13.3714
    num.toPrecision(2); // 13
    num.toPrecision(3); // 13.4
    num.toPrecision(10); // 13.37140000
    var num = 0.001658853;
    num.toPrecision(); // 0.001658853
    num.toPrecision(2); // 0.0017
    num.toPrecision(3); // 0.00166
    num.toPrecision(10); // 0.001658853000

    // valueOf - primitive value of a number
    // no reason to use
    var numObj = new Number(10); // typeof numObj = object
    var num = numObj.valueOf(); // typeof num = number
  

ES2015


    Number.EPSILON; // 2.220446049250313e-16
    Number.MIN_SAFE_INTEGER; // -9007199254740991
    Number.MAX_SAFE_INTEGER; // 9007199254740991

    // isSafeInteger = can be exactly represented as an IEEE-754 double precision number
    // all integers from (253 - 1) to -(253 - 1)
    Number.isSafeInteger(123) //true
    Number.isSafeInteger(-123) //true
    Number.isSafeInteger(5-2) //true
    Number.isSafeInteger(0) //true
    Number.isSafeInteger(0.5) //false
    Number.isSafeInteger(Math.pow(2, 53)) //false
    Number.isSafeInteger(Math.pow(2, 53) - 1) //true
    Number.isSafeInteger('123') //false
    Number.isSafeInteger(false) //false
    Number.isSafeInteger(Infinity) //false
    Number.isSafeInteger(-Infinity) //false
    Number.isSafeInteger(0 / 0) //false

    // isInteger = value is of the type Number, and an integer (a whole number)
    Number.isInteger(123) //true
    Number.isInteger(-123) //true
    Number.isInteger(5-2) //true
    Number.isInteger(0) //true
    Number.isInteger(0.5) //false
    Number.isInteger('123') //false
    Number.isInteger(false) //false
    Number.isInteger(Infinity) //false
    Number.isInteger(-Infinity) //false
    Number.isInteger(0 / 0) //false

    // isFinite = value is of the type Number, and equates to a finite number
    Number.isFinite(123) //true
    Number.isFinite(-1.23) //true
    Number.isFinite(5-2) //true
    Number.isFinite(0) //true
    Number.isFinite('123') //false
    Number.isFinite('Hello') //false
    Number.isFinite('2005/12/12') //false
    Number.isFinite(Infinity) //false
    Number.isFinite(-Infinity) //false
    Number.isFinite(0 / 0) //false
  

ES2020


    const theBiggestInt = 9007199254740991n;

    const alsoHuge = BigInt(9007199254740991); // 9007199254740991n
    const hugeButString = BigInt('9007199254740991'); // 9007199254740991n

    const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER); // 9007199254740991
    const maxPlusOne = previousMaxSafe + 1n; // 9007199254740992n
    const theFuture = previousMaxSafe + 2n; // 9007199254740993n, this works now!
    const multi = previousMaxSafe * 2n; // 18014398509481982n
    const subtr = multi - 10n; // 18014398509481972n
    const mod = multi % 10n; // 2n
    const bigN = 2n ** 54n; // 18014398509481984n
    bigN * -1n // -18014398509481984n

    const expected = 4n / 2n; // 2n
    const rounded = 5n / 2n; // 2n, not 2.5n

    0n === 0 // false
    0n == 0 // true

    const mixed = [4n, 6, -12n, 10, 4, 0, 0n]; // [4n, 6, -12n, 10, 4, 0, 0n]
    mixed.sort(); // [-12n, 0, 0n, 10, 4n, 4, 6]

    function isPrime(p) {
      for (let i = 2n; i * i <= p; i++) {
        if (p % i === 0n) return false;
      }
      return true;
    }
    function nthPrime(nth) { // takes a BigInt as an argument and returns a BigInt
      let maybePrime = 2n;
      let prime = 0n;
      while (nth >= 0n) {
        if (isPrime(maybePrime)) {
          nth -= 1n;
          prime = maybePrime;
        }
        maybePrime += 1n;
      }
      return prime;
    }
  

ES2021


    // --- Regular Number Literals
    let budget = 1_000_000_000_000;
    console.log(budget === 10 ** 12); // true

    // --- Binary Literals
    let nibbles = 0b1010_0001_1000_0101;
    console.log(!!(nibbles & (1 << 7))); // true

    // --- Hex Literal
    let message = 0xA0_B0_C0;
    let a = (message >> 16) & 0xFF;
    console.log(a.toString(16), a); // a0, 160
    let b = (message >> 8) & 0xFF;
    console.log(b.toString(16), b); // b0, 176
    let c = message & 0xFF;
    console.log(c.toString(16), b); // c0, 192

    // --- BigInt Literal
    const max = 2n ** (64n - 1n) - 1n;
    console.log(max === 9_223_372_036_854_775_807n);
    let budget = 1_000_000_000_000n;
    console.log(budget === BigInt(10 ** 12)); // true
    // Valid
    1_1n;
    1_000n;
    99999999_111111111_00000000n;
    // Invalid: SyntaxError!
    1_n;
    0_n;
    1000000_n;
    1_000_000_n;

    // --- Octal Literal
    let x = 0o1234_5670;
    let partA = (x & 0o7777_0000) >> 12; // 3 bits per digit
    let partB = x & 0o0000_7777;
    console.log(partA.toString(8)); // 1234
    console.log(partB.toString(8)); // 5670
  

Arrays


    var cars = ["Saab", "Volvo", "BMW"];
    var cars = [
      "Saab",
      "Volvo",
      "BMW"
    ];
    // access and modify by index
    var name = cars[0];
    cars[0] = "Opel";

    cars[cars.length] = "Subaru";
    delete fruits[0]; // set first element to undefined

    // variables of different types in the same Array
    myArray[0] = Date.now;
    myArray[1] = myFunction;
    myArray[2] = myCars;
  

CHECK


    Array.isArray(cars);  // Array.isArray(obj) = true/false
    cars.constructor.toString().indexOf("Array") > -1;
    myArray.constructor === Array; //  if the object is an Array function
    cars instanceof Array;

    // arr.every( function(currentValue, index, arr), as_this_val )
    // true/false - if ALL element has passed the test
    var numbers = [4, 9, 16, 25, 29];
    var allOver18 = numbers.every(myFunction);
    function myFunction(value, index, array) {
      return value > 18;
    }

    // arr.some( function(currentValue, index, arr), as_this_val )
    // true/false - if SOME elements passed the test
    var numbers = [4, 9, 16, 25, 29];
    var allOver18 = numbers.some(myFunction);
    function myFunction(value, index, array) {
      return value > 18;
    }
  

PROPERTIES


    // length property sets or returns the number of elements in that array
    // truncates values or extends with undefined values

    var namelistA = new Array(4294967296); //2 to the 32nd power = 4294967296
    var namelistC = new Array(-100) //negative sign
    console.log(namelistA.length); //RangeError: Invalid array length
    console.log(namelistC.length); //RangeError: Invalid array length
    var namelistB = [];
    namelistB.length = Math.pow(2,32)-1; //set array length less than 2 to the 32nd power
    console.log(namelistB.length);

    fruits[5] = 'mango';
    console.log(fruits[5]); // 'mango'
    console.log(Object.keys(fruits));  // ['0', '1', '2', '5']
    console.log(fruits.length); // 6

    fruits.length = 2;
    console.log(Object.keys(fruits)); // ['0', '1']
    console.log(fruits.length); // 2
  

METHODS


    // length property is always one more than the highest array index
    cars.length; // 3

    cars.push("Audi");  // arr.push(el1, el2,...) - add to end, changes the length
    x = cars.push();    // and returns the length

    cars.pop();         // removes the last element, changes the length
    x = cars.pop();     // and returns the value that was "popped out"

    cars.shift();       // removes first element, changes the length
    x = cars.shift();   // and returns the string that was "shifted out"

    cars.unshift("Dodge");// arr.unshift(el1, el2,...) - adds first element, changes the length
    x = cars.unshift(); // and returns the new length

    // arr.slice(start_pos, end_pos) - returns the selected elements in an array
    var slice_cars = cars.slice(1);

    // arr.splice(add_pos, elements_to_remove [,"new","elements",...])
    cars.splice(2, 0, "Honda", "VW");

    // arr.concat(arr_1 [,arr_2,...]) - merge arrays
    var new_cars = ["Dodge", "Honda", "VW"];
    var updated_cars = cars.concat(new_cars);
    var updated_cars = cars.concat(["Dodge", "Honda", "VW"]);

    // array to string
    cars.toString();    // Saab,Volvo,BMW,Audi
    cars.join(" * ");   // Saab * Volvo * BMW * Audi
  

SORT


    // arr.sort( [compareFunction] ) - alphabetically or by function
    cars.sort();

    // reverse the order of the elements
    cars.reverse(); // can be used after sort, for descending ordering

    // numeric sort
    var points = [40, 100, 1, 5, 25, 10];

    points.sort(function(a, b){return a - b}); // ascending
    // points[0] = lowest, points[points.length-1] = highest value

    points.sort(function(a, b){return b - a}); // descending
    // points[0] = highest, points[points.length-1] = lowest value

    points.sort(function(a, b){return 0.5 - Math.random()}); // random sort

    Math.max.apply(null, arr); // highest number in an array
    // Math.max.apply([1, 2, 3]) is equivalent to Math.max(1, 2, 3)

    Math.min.apply(null, arr); // lowest number in an array
    // Math.min.apply([1, 2, 3]) is equivalent to Math.min(1, 2, 3)

    function myArrayMax(arr) {
        var len = arr.length, max = -Infinity;
        while (len--) {
            if (arr[len] > max) {
                max = arr[len];
            }
        }
        return max;
    }

    function myArrayMin(arr) {
        var len = arr.length, min = Infinity;
        while (len--) {
            if (arr[len] < min) {
                min = arr[len];
            }
        }
        return min;
    }

    // sorting objects array
    var cars = [
      {type:"Volvo", year:2016},
      {type:"Saab", year:2001},
      {type:"BMW", year:2010}
    ];

    cars.sort (function(a, b) {return a.year - b.year}); // numeric

    cars.sort (function(a, b) { // string
      var x = a.type.toLowerCase();
      var y = b.type.toLowerCase();
      if (x < y) {return -1;}
      if (x > y) {return 1;}
      return 0;
    });
  

ITERATION


    // arr.forEach( function(currentValue, index, arr), as_this_val )
    var numbers = [65, 44, 12, 4];
    var sum = 0;
    function myFunction(item, index, arr) {
      sum += item; // calculate sum of all values
      arr[index] = item * document.getElementById("multiplyWith").value; // multiply all values
      demo.innerHTML = numbers;
    }
    numbers.forEach(myFunction);

    // arr.map(function( function(currentValue, index, arr), as_this_val )
    var numbers1 = [4, 9, 16, 25];
    var numbers2 = numbers1.map(myFunction);
    function myFunction(value, index, array) {
      return value * 2;
    }

    // arr.filter( function(currentValue, index, arr), as_this_val )
    // array with elements that passed the test OR empty array
    var numbers = [4, 9, 16, 25];
    var over18 = numbers.filter(myFunction);
    function myFunction(value, index, array) {
      return value > 18;
    }

    // arr.reduce(function(total, currentValue, currentIndex, arr), initialValue)
    // works from left-to-right
    var numbers1 = [4, 9, 16, 25];
    var sum = numbers1.reduce(myFunction);
    function myFunction(
      total, // initial OR previously returned value
      value,
      index,
      array
    ) {
      return total + value;
    }

    // arr.reduceRight(function(total, currentValue, currentIndex, arr), initialValue)
    // works from right-to-left
    var numbers1 = [4, 9, 16, 25];
    var sum = numbers1.reduce(myFunction);
    function myFunction(
      total, // initial OR previously returned value
      value,
      index,
      array
    ) {
      return total + value;
    }

    // arr.indexOf(item, start_pos)
    // position of element OR -1
    var fruits = ["Apple", "Orange", "Apple", "Mango"];
    var a = fruits.indexOf("Apple");

    // lastIndexOf(item, start_pos)
    // position of element from the end of the array OR -1
    var fruits = ["Apple", "Orange", "Apple", "Mango"];
    var a = fruits.lastIndexOf("Apple");
  

ES2015


    // arr.find( function(currentValue, index, arr), as_this_val )
    // find and return first element that passed the test OR undefined
    var numbers = [4, 9, 16, 25, 29];
    var first = numbers.find(myFunction);
    function myFunction(value, index, array) {
      return value > 18;
    }

    // arr.findIndex( function(currentValue, index, arr), as_this_val )
    // find and return index of first element that passed the test OR -1
    var numbers = [4, 9, 16, 25, 29];
    var first = numbers.findIndex(myFunction);
    function myFunction(value, index, array) {
      return value > 18;
    }

    // arr.fill(value [,start_pos [,end_pos]])
    // returns array filled with a static value
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.fill("Kiwi", 2, 4);
    // copyWithin( target_pos [,start_pos [,end_pos]] )
    var fruits = ["Banana", "Orange", "Apple", "Mango", "Kiwi", "Papaya"];
    fruits.copyWithin(2, 0, 2);  // Banana,Orange,Banana,Orange,Kiwi,Papaya

    // entries() -  returns an Array Iterator object with key/value pairs
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    var x = fruits.entries();
    // x.next().value = 0,Banana
    // x.next().value = 1,Orange
    // ...

    // keys() -  returns an Array Iterator object with keys of an array
    var x = fruits.keys();
    // x.next().value = 0
    // x.next().value = 1
    // ...

    // array.from(object, mapFunction, thisValue)
    // returns an Array object from any object with a length property or an iterable object
    var myArr = Array.from("ABCDEFG"); // [ "A", "B", "C", "D", "E", "F", "G" ]
  

ES2016


    // arr.includes(search_val [,start_pos]) = true/false
    // whether an array contains a specified element
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    var n = fruits.includes("Banana"); // true
    var n = fruits.includes("Banana", 3); // false
  

ES2019


    // flat(depth)
    let courseStudents = [
      [ 'Janet', 'Martha', 'Bob', [ 'Phil', 'Candace' ] ],
      [ 'Wilson', 'Taylor' ],
      [ 'Edith', 'Jacob', 'Peter', 'Betty' ]
    ]
    let flattenOneLevel = courseStudents.flat(1); // [ 'Janet', ... , [ 'Phil', 'Candace' ], 'Wilson', ... , 'Betty' ]
    let flattenTwoLevels = courseStudents.flat(2); // [ 'Janet', 'Martha', 'Bob', 'Phil', 'Candace', ... , 'Betty' ]
    let alwaysFlattened = courseStudents.flat(Infinity); // [ 'Janet', 'Martha', 'Bob', 'Phil', 'Candace', ... , 'Betty' ]

    // flatMap() - equivalent of combing map and flat with no argument
    // before ES2019
    let grades = [78, 62];
    let curved = grades.map(grade => [grade, grade + 7]); // [ [ 78, 85 ], [ 62, 69 ] ]
    let flatMapped = [].concat.apply([], curved); // [ 78, 85, 62, 69 ]
    // improve with flat()
    let flatMapped = grades.map(grade => [grade, grade + 7]).flat(); // [ 78, 85, 62, 69 ]
    // with ES2019 flatMap, will only flatten one level
    let flatMapped = grades.flatMap(grade => [grade, grade + 7]); // [ 78, 85, 62, 69 ]
  

ES2022


    const array1 = [5, 12, 8, 130, 44];
    array1.at(2); // 8
    array1.at(-2); // 130
  

Typed Array


    new TypedArray(); // new in ES2017
    new TypedArray(length);
    new TypedArray(typedArray);
    new TypedArray(object);
    new TypedArray(buffer [, byteOffset [, length]]);
    where TypedArray() is one of:
    Int8Array();          // -128 to 127
    Uint8Array();         // 0 to 255
    Uint8ClampedArray();  // 0 to 255
    Int16Array();         // -32768 to 32767
    Uint16Array();        // 0 to 65535
    Int32Array();         // -2147483648 to 2147483647
    Uint32Array();        // 0 to 4294967295
    Float32Array();       // 1.2x10-38 to 3.4x1038
    Float64Array();       // 5.0x10-324 to 1.8x10308

    const typedArray1 = new Int8Array(8);
    typedArray1[0] = 32;
    console.log(typedArray1); // Int8Array [32, 0, 0, 0, 0, 0, 0, 0]
    const typedArray2 = new Int8Array(typedArray1);
    typedArray2[1] = 42;
    console.log(typedArray2); // Int8Array [32, 42, 0, 0, 0, 0, 0, 0]

    // 8-byte buffer with a Int32Array view referring to the buffer
    var buffer = new ArrayBuffer(16); // buffer.byteLength = 16
    var view   = new Int32Array(buffer);

    var view1 = new DataView(buffer);
    var view2 = new DataView(buffer,12,4);    //from byte 12 for the next 4 bytes
    view1.setInt8(12, 42);                    // put 42 in slot 12
    console.log(view2.getInt8(0));            // 42
  

Date()


    var d = new Date(); // current date and time, object

    // one parameter will be interpreted as new Date(milliseconds)
    var d = new Date(2018); // Thu Jan 01 1970 02:00:02 GMT+0200
    // one day (24 hours) is 86 400 000 milliseconds
    // negative values are allowed

    // year, month, day, hour, minute, second, and millisecond
    var d = new Date(2018, 11, 24, 10, 33, 30, 0);
    // year, month
    var d = new Date(2018, 11);

    // one and two digit years will be interpreted as 19xx
    var d = new Date(99, 11, 24); // Fri Dec 24 1999
    var d = new Date(9, 11, 24); // Fri Dec 24 1909

    // ----- ISO DATES
    // prefered way to define date
    // YYYY-MM-DD
    // YYYY-MM-DDTHH:MM:SSZ
    var d = new Date("2018-03-25");
    var d = new Date("2018-03");
    var d = new Date("2018");

    // Omitting T or Z in a date-time string can give different result in different browser
    var d = new Date("2018-03-25T12:00:00Z");
    var d = new Date("2018-03-25T12:00:00-06:30"); // -06:30

    // ----- SHORT DATES - "MM/DD/YYYY"
    var d = new Date("03/25/2018");
    // !!! may produce errors :
    var d = new Date("2018-3-25");
    var d = new Date("2018/03/25");
    var d = new Date("25-03-2018");

    // ----- LONG DATES - most often written with a "MMM DD YYYY"
    // month and day can be in any order
    // month can be written in full (January), or abbreviated (Jan)
    // commas are ignored, names are case insensitive
    var d = new Date("Mar 25 2018");
    var d = new Date("25 Mar 2018");
    var d = new Date("January 25 2018");
    var d = new Date("Jan 25 2018");
    var d = new Date("JANUARY, 25, 2018");

    // ----- PARSE DATE STRING
    var d = Date.parse("March 21, 2012");
  

CHECK


    myDate.constructor.toString().indexOf("Date") > -1;
    myDate.constructor === Date; //  if the object is an Date function
  

METHODS


    var d = Date.now(); // Get the time. ECMAScript 5

    // milliseconds between specified date and midnight of 1970/01/01 according to UTC
    // (year, month, day, hours, minutes, seconds, millisec)
    var d = Date.UTC(2018, 02, 30); // 1333065600000

    d.toISOString(); // 2018-08-24T15:13:11.341Z
    d.toUTCString(); // UTC string = Fri, 24 Aug 2018 14:31:32 GMT

    d.toJSON(); // JSON date = YYYY-MM-DDTHH:mm:ss.sssZ = 2018-08-24T15:15:17.565Z

    d.toDateString(); // Fri Aug 24 2018
    d.toTimeString(); // 18:21:58 GMT+0300 (GTB Daylight Time)

    // using locale conventions
    // date (not the time) portion of a Date object as a string
    d.toLocaleDateString(); // 8/24/2018
    // time portion of a Date object as a string
    d.toLocaleTimeString(); // 6:18:25 PM
    // Date object to a string
    d.toLocaleString(); // 8/24/2018, 6:20:07 PM
  

GET METHODS


    d.getFullYear(); // year as a four digit number (yyyy)
    d.getMonth(); // month as a number (0-11)
    d.getDate(); // day as a number (1-31)
    d.getHours(); // hour (0-23)
    d.getMinutes(); // minute (0-59)
    d.getSeconds(); // second (0-59)
    d.getMilliseconds(); // millisecond (0-999)
    d.getTime(); // time (milliseconds since January 1, 1970)
    d.getDay(); // weekday as a number (0-6)

    d.getUTCDate(); // same as getDate(), but UTC date
    d.getUTCDay(); // same as getDay(), but UTC day
    d.getUTCFullYear(); // sSame as getFullYear(), but UTC year
    d.getUTCHours(); // same as getHours(), but UTC hour
    d.getUTCMilliseconds(); // same as getMilliseconds(), but UTC milliseconds
    d.getUTCMinutes(); // same as getMinutes(), but UTC minutes
    d.getUTCMonth(); // same as getMonth(), but UTC month
    d.getUTCSeconds(); // same as getSeconds(), but UTC seconds

    d.getTimezoneOffset(); // time difference between UTC time and local time, in minutes
  

SET METHODS


    var d = new Date("2018-03-25T12:00:00Z");

    d.setDate(); // day as a number (1-31)
    d.setFullYear(); // year (optionally month and day)
    d.setHours(); // hour (0-23)
    d.setMilliseconds(); // milliseconds (0-999)
    d.setMinutes(); // minutes (0-59)
    d.setMonth(); // month (0-11)
    d.setSeconds(); // seconds (0-59)
    d.setTime(); // time (milliseconds since January 1, 1970)

    d.setUTCDate(); // day according to universal time
    d.setUTCFullYear(); // year according to universal time
    d.setUTCHours(); // hour according to universal time
    d.setUTCMilliseconds(); // milliseconds according to universal time
    d.setUTCMinutes(); // minutes according to universal time
    d.setUTCMonth(); // month according to universal time
    d.setUTCSeconds(); // seconds according to universal time
  

Objects


    if (typeof myObj !== "undefined" && myObj !== null) { ... }

    // object definition
    var person = {
      firstName:"Andre",
      lastName:"IT",
      age:31,
      eyeColor:"green",
      language : "NO",
      new : true, // reserved word as property name - ES5
      fullName : function() { // object method , same as getter/setter
        return this.firstName + " " + this.lastName;
      },
      get lang() { // getter
        return this.language;
      },
      set lang(value) { // setter
        this.language = value.toUpperCase();
      },
      //-----ES2015
      property( parameters… ) {},
      l() { return this.language; }
      async property( parameters… ) {},
      async f() {
        await some_promise;
      }
      async* generator( parameters… ) {},
      async* f() {
        yield 1;
        yield 2;
        yield 3;
      }
      [property]( parameters… ) {}, // computed key
      ['foo' + 2]() {
        return 2;
      }
      *[generator]( parameters… ) {}, // computed key
      * g() {
        var index = 0;
        while (true)
        yield index++;
      }
      async [property]( parameters… ) {}, // computed key
    };
    var x_p = person; // object x_p is not a copy of person, it is person object
    x_p.age = 10;     // this will change both x_p.age and person.age !

    //-----ES2015 - computed properties - rejected by JSON !
    var param = 'size';
    var i = 0;
    var a = {
      ['foo' + ++i]: i,
      ['foo' + ++i]: i,
      ['foo' + ++i]: i,
      [param]: 12,
      ['mobile_' + param]: 4
    };

    // objects constructor
    function Person(first, last, age, eye) {
      this.firstName = first;
      this.lastName = last;
      this.age = age;
      this.eyeColor = eye;
      this.changeNames = function (f, l) { // default method for all instance of this constructor
          this.firstName = f;
          this.lastName = l;
      };
    }
    var johnDoe = new Person("John", "Doe", 50, "blue"); // Person instance

    // ADD property ONLY for specific object
    person.nationality = "English";
    johnDoe.UCnames = function () {
      return this.firstName.toUpperCase() + " " + this.lastName.toUpperCase();
    };
    johnDoe.UCnames(); // using own method
    johnDoe.changeNames("J", "D"); // using parent constructor

    //-----ES2015
    var a = 'foo', b = 42, c = {};
    var o = {a, b, c}; // same as: var o = {a: a, b: b, c: c}
    o.a === {a}.a // true

    // ACCESS property
    person.age; // same as: person["age"]
    person[("a"+"ge")];
    person.fullName();
    person.fullName;    // fullName-function definition
    person.lang();        // usage of a getter
    person.firstName.toUpperCase(); // built-in String object method for string property

    // CHECK
    person.hasOwnProperty('language'); // true
    "key" in obj // true, regardless of the actual value
    !("key" in obj) // true if "key" doesn't exist in object

    // EDIT property of a specific object
    person.firstName = "A";
    person.lang = "en";   // usage of a setter
    johnDoe.firstName = "J";

    // DELETE property
    delete person.age;  // or delete person["age"];

    // Enumerate Properties
    for (x in person) {
      txt += person[x];
    }

    //-----ES2015 - enhanced object literals
    var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}

    var accountService = {
      __proto__: serviceBase,
      getAccounts,
      toString() {
        return JSON.stringify((super.valueOf()))
      },
      getUrl() {
        return "http://" + this.url + ':' + this.port
      },
      [ 'valueOf_' + getAccounts().join('_') ]: getAccounts()
    };

    accountService.valueOf_1_2_3; // [1,2,3]
    accountService.port; // 3000
    accountService.url; // azat.co
    accountService.getUrl(); // azat.co
  

PROTOTYPE


    // add property for ALL objects of a Person objects constructor
    Person.prototype.LCnames = function() {
      return this.firstName.toLowerCase() + " " + this.lastName.toLowerCase();
    };

    // CLASSICAL SINGLE/MULTIPLE INHERITANCE
    function gameArea() {   // gameArea - superclass
      this.id = 7;
      this.doit = function() { console.info('doit'); }
    }
    function Shape() {      // Shape - superclass
      this.x = 0;
      this.y = 0;
    }
    Shape.prototype.move = function(x, y) { // Shape - superclass method
      this.x += x;
      this.y += y;
      console.info('Shape moved.');
    };

    function Rectangle() {    // Rectangle - subclass
      gameArea.call(this);    // call super constructor - single/first inheritance
      Shape.call(this);       // call super constructor - next inheritance
    }
    // all newly gameArea properties will be available automatically for Rectangle
    Rectangle.prototype = Object.create(gameArea.prototype); // inherit single/first class
    // you have to reassign superclass to have new properties update, if something changed
    Object.assign(Rectangle.prototype, Shape.prototype); // mixin another
    Rectangle.prototype.constructor = Rectangle; // re-assign constructor

    var rect = new Rectangle();
    // rect instanceof gameArea = true - rect is an instance of Shape
    // rect instanceof Shape = false - rect is not an instance of Shape
    // rect instanceof Rectangle = true - rect is an instance of Rectangle
    rect.move(1, 1);
    rect.doit();
    gameArea.prototype.doit2 = function() { console.info('doit2'); };
    rect.doit2(); // = 'doit2' - property is available
    Shape.prototype.doit3 = function() { console.info('doit3'); };
    rect.doit3(); // = 'undefined' - re-assign Shape class to have this method available in Rectangle
  

METHODS


    // --- Object.create() - create new object using an existing object __proto__
    // --- Object.create(null) = {} - no JS Object.prototype inheritance
    var new_obj = Object.create(Object.prototype, {
      foo: {      // foo is a regular 'value property'
        writable: true,
        configurable: true,
        value: 'hello'
      },
      bar: {      // bar is a getter-and-setter (accessor) property
        configurable: false,
        get: function() { return 10; },
        set: function(value) { console.log('Setting `o.bar` to', value); }
      },
      baz: {      // with ES2015 Accessors
        get() { return 10; },
        set(value) { console.log('Setting `o.baz` to', value); }
      }
    });
    // --- Object.assign()
    // copy values of all enumerable own properties from one or more objects
    var new_obj_copy = Object.assign({}, new_obj);              // cloning
    let new_obj_copy = JSON.parse(JSON.stringify(new_obj));     // deep cloning

    // --- Object.defineProperty
    Object.defineProperty(person, "incrementAge", {
        get : function () { this.age++; }
    });
    Object.defineProperty(person, "language", {
      value: "EN",
      writable : true,          // allow to change
      enumerable : true,        // allow enumeration
      configurable : false,     // allow reconfiguration
      get : function() { return language },
      set : function(value) { language = value.toUpperCase() }
    });
    Object.defineProperty(person, "language", {enumerable:false});
    // --- Object.defineProperties
    Object.defineProperties(person, {
      'property1': {
        value: true,
        writable: true
      },
      'property2': { ... }
    });

    // obj.hasOwnProperty(prop) - own, not inherited property
    person.hasOwnProperty('language'); // true
    // Object.hasOwn(instance, prop)
    Object.hasOwn(person, 'language'); // true

    // --- Object.getOwnPropertyDescriptor(obj, prop)
    // --- Object.getOwnPropertyDescriptors(obj)
    const foo_desc = Object.getOwnPropertyDescriptor(new_obj, 'foo');
    const new_obj_desc = Object.getOwnPropertyDescriptors(new_obj);
    console.log(foo_desc.configurable);   // true
    console.log(foo_desc.value);          // 'hello'
    console.log(new_obj_desc,foo.configurable);   // true
    console.log(new_obj_desc.foo.value);          // 'hello'
    // decriptors data: value, writable, configurable, enumerable [, get, set]

    // --- Object.getOwnPropertyNames(obj)
    // array of all properties (including non-enumerable, except which use Symbol)
    // found directly upon a given object
    Object.getOwnPropertyNames(new_obj); // ["foo","bar","baz"]
    // --- Object.getOwnPropertySymbols(obj) - empty unless you set symbol properties on the object

    // obj.propertyIsEnumerable(prop)
    person.propertyIsEnumerable(property1); // false - it was set by default by defineProperty

    var obj = { a: 5, b: 7, c: 9 };
    // --- Object.entries(obj) = array of [key,value] pairs
    Object.entries(obj).forEach(([key, value]) => {
      console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
    });
    // --- Object.keys(obj) = array of property names
    Object.keys(obj); // ["a","b","c"]
    // --- Object.values(obj) = array of property values
    Object.values(obj); // [5,7,9]

    // --- Object.fromEntries (ES2019) - reverse of Object.entries
    obj = Object.fromEntries([['a', 0], ['b', 1]]); // { a: 0, b: 1 }
    // object-to-object
    obj = { abc: 1, def: 2, ghij: 3 };
    res = Object.fromEntries(
      Object.entries(obj)
      .filter(([ key, val ]) => key.length === 3)
      .map(([ key, val ]) => [ key, val * 2 ])
    ); // res is { 'abc': 2, 'def': 4 }
    // object from existing collection
    map = new Map([ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]);
    obj = Object.fromEntries(map);
    query = Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'));
    arr = [ { name: 'Alice', age: 40 }, { name: 'Bob', age: 36 } ];
    obj = Object.fromEntries(arr.map(({ name, age }) => [ name, age ]));

    // preventExtensions, seal, freeze - are irevertible !
    // --- Object.preventExtensions(obj) / Object.isExtensible(obj)
    // prevents addition of new own object properties but not to prototype, or deleting
    const object1 = {};
    console.log(Object.isExtensible(object1)); // true
    Object.preventExtensions(object1);
    console.log(Object.isExtensible(object1)); // false
    // --- Object.seal(obj) - prevents adding new and configuring of existing properties
    // still allows values change for writable
    Object.seal(object1);
    Object.isSealed(object1); // true
    // --- Object.freeze(obj) - prevents add/remove/change of property, prototype and configs
    Object.freeze(object1);
    Object.isFrozen(object1); // true

    // --- Object.getPrototypeOf()
    const prototype1 = {};
    const object1 = Object.create(prototype1);
    Object.getPrototypeOf(object1) === prototype1 // true

    Object.is('foo', 'foo');     // true
    Object.is(window, window);   // true
    Object.is([], []);           // false

    const date1 = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
    console.log(date1.toLocaleString('ar-EG')); // "٢٠‏/١٢‏/٢٠١٢ ٤:٠٠:٠٠ ص"
    const number1 = 123456.789;
    console.log(number1.toLocaleString('de-DE')); // "123.456,789"

    function shallowCopy( original ) {
      // First create an empty object with
      // same prototype of our original source
      var clone = Object.create( Object.getPrototypeOf( original ) );
      var i , keys = Object.getOwnPropertyNames( original );
      for ( i = 0; i < keys.length; i ++ ) {
        // copy each property into the clone
        Object.defineProperty(
          clone,
          keys[ i ],
          Object.getOwnPropertyDescriptor( original , keys[ i ])
        );
      }
      return clone ;
    }
  

Operators

Comparison


    // x = 5

    // equal to
    x == 8 // false
    x == 5 // true
    x == "5" // true

    // equal value and equal type
    x === 5 // true
    x === "5" // false

    // not equal
    x != 8  true

    // not equal value or not equal type
    x !== 5 // false
    x !== "5" // true
    x !== 8 // true

    // greater than
    x > 8 // false

    // less than
    x < 8 // true

    // greater than or equal to
    x >= 8 // false

    // less than or equal to
    x <= 8 // true
  

Logical


    // x = 6, y = 3

    // and
    (x < 10 && y > 1) // true

    // or
    (x == 5 || y == 5) // false

    // not
    !(x == y) // true
  

Combine Logical Operators and Assignment Expressions (ES021)


    // "Or Or Equals" (or, the Mallet operator :wink:)
    a ||= b;
    a || (a = b);
    // "And And Equals"
    a &&= b;
    a && (a = b);
    // "QQ Equals"
    a ??= b;
    a ?? (a = b);

    function example(opts) {
      // Setters are not needlessly called.
      opts.foo ??= 'bar'
      // No repetition of `opts.baz`.
      opts.baz ??= 'qux';
    }
    example({ foo: 'foo' })

    let x = 0;
    const obj = {
      get x() {
        return x;
      },
      set x(value) {
        console.log('setter called');
        x = value;
      }
    };
    // This always logs "setter called"
    obj.x += 1;
    assert.equal(obj.x, 1);
    // Logical operators do not call setters unnecessarily
    // This will not log.
    obj.x ||= 2;
    assert.equal(obj.x, 1);
    // But setters are called if the operator does not short circuit
    // "setter called"
    obj.x &&= 3;
    assert.equal(obj.x, 3);

    document.getElementById('previewZone').innerHTML ||= '<i>Nothing to preview</i>';
  

Conditional (Ternary)


    age = Number(age);
    if (isNaN(age)) {
      voteable = "Input is not a number";
    } else {
      voteable = (age < 18) ? "Too young" : "Old enough";
    }

    var cond1 = true,
    cond2 = false,
    access = cond1 ? (cond2 ? "true true": "true false") : (cond2 ? "false true" : "false false");

    var func2 = function( .. ) {
      return cond1 ? value1s
        : condition2 ? value2
        : condition3 ? value3
        :              value4
    }

    const response = {
      settings: {
        nullValue: null,
        height: 400,
        animationDuration: 0,
        headerText: '',
        showSplashScreen: false
      }
    };
    // --- || - or
    const undefinedValue = response.settings.undefinedValue || 'some other default'; // result: 'some other default'
    const nullValue = response.settings.nullValue || 'some other default'; // result: 'some other default'
    // --- ?? - nullish coalescing (ES2020)
    const undefinedValue = response.settings.undefinedValue ?? 'some other default'; // result: 'some other default'
    const nullValue = response.settings.nullValue ?? 'some other default'; // result: 'some other default'
    const headerText = response.settings.headerText ?? 'Hello, world!'; // result: ''
    const animationDuration = response.settings.animationDuration ?? 300; // result: 0
    const showSplashScreen = response.settings.showSplashScreen ?? true; // result: false
    // --- ?. - optional chaining (ES2020)
    var street = user.address?.street
    var fooValue = myForm.querySelector('input[name=foo]')?.value
    // when other value than undefined is desired for the missing case
    // can usually be handled with the Nullish coalescing operator
    const animationDuration = response.settings?.animationDuration ?? 300;
    // interfaces that have optional methods
    iterator.return?.() // manually close an iterator
  

Comparing Different Types


    2 < 12 // true
    2 < "12" // true
    2 < "John" // false
    2 > "John" // false
    2 == "John" // false

    // "2" will be greater than "12", because (alphabetically) 1 is less than 2
    "2" < "12" // false
    "2" > "12" // true
    "2" == "12" // false
  

Arithmetic

Operator Description
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus (Remainder)
++ Increment
-- Decrement

Assignment

Operator Example Same As
= x = y x = y
+= x += y x = x + y
-= x -= y x = x - y
*= x *= y x = x * y
/= x /= y x = x / y
%= x %= y x = x % y
<<= x <<= y x = x << y
>>= x >>= y x = x >> y
>>>= x >>>= y x = x >>> y
&= x &= y x = x & y
^= x ^= y x = x ^ y
|= x |= y x = x | y
**= x **= y x = x ** y

Type

Operator Description
typeof Returns the type of a variable
instanceof Returns true if an object is an instance of an object type

Operator Precedence

Value Operator Description Example
20 ( ) Expression grouping (3 + 4)
       
19 . Member person.name
19 [] Member person["name"]
19 () Function call myFunction()
19 new Create new Date()
       
17 ++ Postfix Increment i++
17 -- Postfix Decrement i--
       
16 ++ Prefix Increment ++i
16 -- Prefix Decrement --i
16 ! Logical not !(x==y)
16 typeof Type typeof x
       
15 ** Exponentiation (ES2016) 10 ** 2
       
14 * Multiplication 10 * 5
14 / Division 10 / 5
14 % Division Remainder 10 % 5
       
13 + Addition 10 + 5
13 - Subtraction 10 - 5
       
12 << Shift left x << 2
12 >> Shift right x >> 2
12 >>> Shift right (unsigned) x >>> 2
       
11 < Less than x < y 
11 <= Less than or equal x <= y
11 > Greater than x > y
11 >= Greater than or equal x >= y
11 in Property in Object "PI" in Math
11 instanceof Instance of Object instanceof Array
       
10 == Equal x == y
10 === Strict equal x === y
10 != Unequal x != y
10 !== Strict unequal x !== y
       
9 & Bitwise AND x & y
8 ^ Bitwise XOR x ^ y
7 | Bitwise OR x | y
6 && Logical AND x && y
5 || Logical OR x || y
4 ? : Condition ? "Yes" : "No"
       
3 += Assignment x += y
3 += Assignment x += y
3 -= Assignment x -= y
3 *= Assignment x *= y
3 %= Assignment x %= y
3 <<= Assignment x <<= y
3 >>= Assignment x >>= y
3 >>>= Assignment x >>>= y
3 &= Assignment x &= y
3 ^= Assignment x ^= y
3 |= Assignment x |= y
       
2 yield Pause Function yield x
1 , Comma 5 , 6

Math.*

RANDOM


    Math.random();     // returns a random number, always lower than 1
    Math.floor(Math.random() * 10);     // returns a random integer from 0 to 9
    Math.floor(Math.random() * 11);      // returns a random integer from 0 to 10
    Math.floor(Math.random() * 100);     // returns a random integer from 0 to 99
    Math.floor(Math.random() * 101);     // returns a random integer from 0 to 100
    Math.floor(Math.random() * 10) + 1;  // returns a random integer from 1 to 10
    Math.floor(Math.random() * 100) + 1; // returns a random integer from 1 to 100

    // between min (included) and max (excluded)
    function getRndInteger(min, max) {
      return Math.floor(Math.random() * (max - min) ) + min;
    }

    // between min and max (both included)
    function getRndInteger(min, max) {
      return Math.floor(Math.random() * (max - min + 1) ) + min;
    }
  

METHODS


    Math.random();     // returns a random number, always lower than 1
    Math.random() < 0.5
    Math.floor(Math.random() * 10);     // returns a random integer from 0 to 9
    Math.floor(Math.random() * 11);      // returns a random integer from 0 to 10
    Math.floor(Math.random() * 100);     // returns a random integer from 0 to 99
    Math.floor(Math.random() * 101);     // returns a random integer from 0 to 100
    Math.floor(Math.random() * 10) + 1;  // returns a random integer from 1 to 10
    Math.floor(Math.random() * 100) + 1; // returns a random integer from 1 to 100

    Math.ceil(4.4);     // returns 5
    Math.floor(4.7);    // returns 4

    Math.min(0, 150, 30, 20, -8, -200);  // returns -200
    Math.max(0, 150, 30, 20, -8, -200);  // returns 150

    Math.round(4.7);    // returns 5
    Math.round(4.4);    // returns 4

    Math.pow(8, 2);      // returns 64
    Math.sqrt(64);      // returns 8

    Math.abs(-4.7);     // absolute value = 4.7

    Math.sin(90 * Math.PI / 180);     // returns 1 (the sine of 90 degrees)
    Math.asin(0.5); // arcsine of 0.5 = 0.5235987755982989

    Math.cos(3);     // cosine value of 3 = -0.9899924966004454
    Math.acos(0.5); // arccosine of 0.5 = 1.0471975511965979

    Math.tan(90); // tangent of the number 90 = -1.995200412208242
    Math.atan(2); // arctangent of the number 2 = 1.1071487177940904
    Math.atan2(8, 4); // arctangent of 8/4 = 1.1071487177940904

    Math.log(2); // natural logarithm of a number 2 = 0.6931471805599453
    Math.log2(8); // 3
    Math.log10(100); // 2
  

ES2015


    Math.cbrt(125); // cubic root of 125 = 5

    Math.trunc(8.76); // integer part of 8.76 = 8

    Math.sign(-8); // -1
    Math.sign(3); // 1
    Math.sign(0); // 0
    Math.sign(NaN); // NaN
    Math.sign(-Infinity); // -1
    Math.sign(Infinity); // 1

    Math.sinh(3); // hyperbolic sine value of 3 = 10.017874927409903
    Math.cosh(3); // hyperbolic cosine value of 3 = 10.067661995777765
    Math.tanh(1); // hyperbolic tangent of the number 1 = 0.7615941559557649
    Math.asinh(1); // hyperbolic arcsine of 1 = 0.881373587019543
    Math.acosh(2); //  hyperbolic arccosine of 2 = 1.3169578969248166
    Math.atanh(0.5); // hyperbolic arctangent of 0.5 = 0.5493061443340548
  

CONSTANTS


    Math.E;       // 2.718281828459045
    Math.PI;      // 3.141592653589793
    Math.SQRT2;   // 1.4142135623730951
    Math.SQRT1_2; // 0.7071067811865476
    Math.LN2;     // 0.6931471805599453
    Math.LN10;    // 2.302585092994046
    Math.LOG2E;   // 1.4426950408889634
    Math.Log10E;  // 0.4342944819032518
  

Conditions


    // IF
    if (hour < 18) {
      greeting = "Good day";
    }

    // IF...ELSE
    if (hour < 18) {
      greeting = "Good day";
    } else {
      greeting = "Good evening";
    }

    // IF...ELSEIF...ELSE
    if (time < 10) {
      greeting = "Good morning";
    } else if (time < 20) {
      greeting = "Good day";
    } else {
      greeting = "Good evening";
    }
    // OR
    greeting =
      time < 10 ? "Good morning"
      : time < 20 ? "Good day"
      : "Good evening";

    // SWITCH
    // uses strict comparison (===)
    switch(expression) {
      case x:
        // code block
        break;
      case y:
        // code block
        break;
      default: // does not have to be the last case in a switch block
        // code block
        // break;
    }

    switch (new Date().getDay()) {
      case 4:
      case 5:
        text = "Soon it is Weekend";
        break;
      case 0:
      case 6:
        text = "It is Weekend";
        break;
      default:
        text = "Looking forward to the Weekend";
    }

    if (conditionA) {
      outcome1()
    } else if (conditionB) {
      if (conditionC) {
        outcome2()
      } else {
        outcome3()
      }
    } else {
      outcome4()
    }
    // EQUAL TO:
    conditionA ? outcome1()
    : conditionB && conditionC ? outcome2()
    : conditionB ? outcome3()
    : outcome4()
  

Loop/Break/Continue


    // FOR - loops through a block of code a number of times

    // some statements can be executed before OR inside loop
    for (
      // optional, executed (one time) before the execution of the code block
      statement_1_value_1,... ;
      // optional, condition(s) for executing the code block, true = continue execution
      // if ommited provide a break inside the loop
      statement_2 ;
      statement_3  // optional, executed (every time) after the code block has been executed
    ) {
      // code block to be executed
    }

    var cars = ["BMW", "Volvo", "Saab", "Ford"];
    var i, len, text;
    for (
      i = 0, len = cars.length, text = ""; // better to define before loop !!!
      i < len;
      i++
    ) {
      text += cars[i] + " - ";
    }

    // FOR/IN - loops through the properties of an object

    var person = {fname:"John", lname:"Doe", age:25}, text = "", x;
    for (x in person) {
      text += person[x];
    }

    // WHILE - loops through a block of code while a specified condition is true

    while (condition) {
      // code block to be executed
    }

    while (i < 10) {
      text += "The number is " + i;
      i++;
    }

    // DO/WHILE - execute the code block once, then repeat as long the condition is true

    do {
      // code block to be executed
    }
    while (condition);

    do {
      text += "The number is " + i;
      i++;
    }
    while (i < 10);

    // FOR...OF
    for (let value of [10, 20, 30]) { value += 1; console.log(value); } // 11 // 21 // 31

    (function() { for (let arg of args) { console.log(arg); } })(1, 2, 3); // 1 // 2 // 3

    // This will only work in platforms that have implemented NodeList.prototype[Symbol.iterator]
    let articleParagraphs = document.querySelectorAll('article > p');
    for (let paragraph of articleParagraphs) { paragraph.classList.add('read'); }

    // ----------------------------------------
    var cars = ["BMW", "Volvo", "Saab", "Ford"], i = 0, text = "";
    for (;cars[i];) {
      text += cars[i] + ", "; i++;
    }
    var cars = ["BMW", "Volvo", "Saab", "Ford"], i = 0, text = "";
    while (cars[i]) {
      text += cars[i] + ", "; i++;
    }
    // ----------------------------------------

    // BREAK

    for (i = 0; i < 10; i++) {
      if (i === 3) { break; } // exit loop and execute next code
      text += " number is " + i;
    }

    // CONTINUE

    for (i = 0; i < 10; i++) {
      if (i === 3) { continue; } // skip number 3 and continue loop
      text += " number is " + i;
    }

    // LABEL

    var i, j;
    loop1:
    for (i = 0; i < 3; i++) { // --- "loop1"
      loop2:
      for (j = 0; j < 3; j++) { // --- "loop2"
        if (i == 1 && j == 1) {
          break loop1; // break on "i = 1, j = 1"
        }
        console.log("i = " + i + ", j = " + j);
      }
    }
    // "i = 0, j = 0" , "i = 0, j = 1" , "i = 0, j = 2" , "i = 1, j = 0" , X

    var cars = ["BMW", "Volvo", "Saab", "Ford"];
    list: {
      text += cars[0] + " ";
      text += cars[1] + " ";
      break list;
      text += cars[2] + " ";
      text += cars[3] + " ";
    }
    // text = BMW,Volvo
  

Functions


    // DECLARATION
    function toCelsius(fahrenheit) { return (5/9) * (fahrenheit-32); }

    var c = toCelsius(77); // function as a value
    var c = "The temperature is " + toCelsius(77); // function as a value in expression
    var e = toCelsius; // function definition as a string

    // EXPRESSION, anonymous function
    var x = function (a, b) {return a * b}; // same as: new Function("a", "b", "return a * b");
    var z = x(4, 3);

    // CONSTRUCTOR
    function myFunction(arg1, arg2) {
      this.firstName = arg1; // this - will refer to newly created object
      this.lastName  = arg2;
    }
    var x = new myFunction("John", "Doe");  // new object
    x.firstName;                            // Will return "John"

    myFunction.length;                      // 2 - parameters expected

    function Employee(name, dept) {
      this.name = name || '';
      this.dept = dept || 'general';
    }

    // arguments object
    function myConcat(separator) {
      var args = Array.prototype.slice.call(arguments, 1);
      return args.join(separator);
    }
    myConcat(', ', 'red', 'orange', 'blue'); // "red, orange, blue"
    myConcat('; ', 'elephant', 'giraffe', 'lion'); // "elephant; giraffe; lion"
    myConcat('. ', 'sage', 'basil', 'oregano'); // "sage. basil. oregano"

    function list(type) {
      var result = '<' + type + 'l><li>';
      var args = Array.prototype.slice.call(arguments, 1);
      result += args.join('</li><li>');
      result += '</li></' + type + 'l>'; // end list
      return result;
    }
    // <ul><li>One</li><li>Two</li><li>Three</li></ul>
    var listHTML = list('u', 'One', 'Two', 'Three');

    // call() - invoke (call) a method with an owner object as an argument (parameter)
    var person = { fullName: function() {
      return this.firstName + " " + this.lastName;
    }}
    var person1 = { firstName:"John", lastName: "Doe" }
    person.fullName.call(person1);  // Will return "John Doe"
    // with arguments
    var person = { fullName: function(city, country) {
      return this.firstName + " " + this.lastName + "," + city + "," + country;
    }};
    var person1 = { firstName:"John", lastName: "Doe" };
    person.fullName.call(person1, "Oslo", "Norway"); // returns John Doe,Oslo,Norway

    // apply() - same as call(), but receives arguments (limited to 65536) as array
    person.fullName.apply(person1, ["Oslo", "Norway"]);
    // apply usefulness - same as: Math.max(1,2,3) but argumnets are configurable
    Math.max.apply(null, [1,2,3]); // first arguments (null) dont matter

    // self-invoking - automatic call of expression function
    (function () {
        var x = "Hello!!";
    })();
  

Callback


    function myFunc(text, callback) {
      setTimeout(function() {
        callback(text);
      }, 2000);
    }
    myFunc('Hello world!', console.log);
    // 'Hello world!'
  

Closure


    var add = (function () { // with self-invoking anonymous function
      var counter = 0; // executed once, to create private counter
      return function () {counter += 1; return counter}
    })();
    add(); // 1
    add(); // 2 ...

    var makeCounter = function() {
      var privateCounter = 0;
      function changeBy(val) { privateCounter += val; }
      return {
        increment: function() { changeBy(1); },
        decrement: function() { changeBy(-1); },
        value: function() { return privateCounter; }
      }
    };
    var counter1 = makeCounter();
    var counter2 = makeCounter();
    alert(counter1.value()); /* Alerts 0 */
    counter1.increment();
    counter1.increment();
    alert(counter1.value()); /* Alerts 2 */
    counter1.decrement();
    alert(counter1.value()); /* Alerts 1 */
    alert(counter2.value()); /* Alerts 0 */

    function makeAdder(x) { return function(y) { return x + y; }; }
    var add5 = makeAdder(5);
    var add10 = makeAdder(10);
    console.log(add5(2));  // 7
    console.log(add10(2)); // 12

    function makeSizer(size) { return function() { document.body.style.fontSize = size + 'px'; }; }
    var size12 = makeSizer(12);
    var size14 = makeSizer(14);
    document.getElementById('size-12').onclick = size12;
    document.getElementById('size-14').onclick = size14;

    function apiConnect(apiKey) {
      function get(route) { return fetch(`${route}?key=${apiKey}`); }
      function post(route, params) {
        return fetch(route, {
          method: 'POST',
          body: JSON.stringify(params),
            headers: {
              'Authorization': `Bearer ${apiKey}`
            }
          })
      } return { get, post } }
    const api = apiConnect('my-secret-key');
    // no need to set API-key animore
    api.get('http://www.example.com/get-endpoint');
    api.post('http://www.example.com/post-endpoint', { name: 'Joe' });
  

ES2015


    // arrow functions
    // in ES5: x = function(x, y) { return x * y; }
    const x = (x, y) => x * y;
    const x = (x, y) => { return x * y };

    (param1, param2, …, paramN) => { return ... }
    singleParam => { return ... }   // parentheses are optional when only one parameter
    () => { return ... }            // when no parameters
    (param1, param2, ...restOfArgs) => { return ... }   // ...restOfArgs parameters
    (param1 = defaultValue1, param2) => { return ... }  // default parameters

    (param1, param2, …, paramN) => expression // implied "return" => { return expression; }

    singleParam => ({foo: bar})     // when returning object

    callback = callback || (() => {});

    (() => 'foobar')(); // 'foobar'; Immediately Invoked Function Expression

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

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

    var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; // dectructuring
    f(); // 6

    var elements = [
      'Hydrogen',
      'Helium',
      'Lithium',
      'Beryllium'
    ];
    // [8, 6, 7, 9] - string length
    elements.map(function(element){ return element.length; });
    elements.map(element => { return element.length; });
    elements.map(element => element.length);
    elements.map(({ length }) => length);

    var arr = [5, 6, 13, 0, 1, 18, 23];
    var sum = arr.reduce((a, b) => a + b); // 66
    var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
    var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46]
    var ids = arr.map(value => `ID is ${value}`) // ['ID is 5',...]
    // More concise promise chains
    promise.then(a => {
      // ...
    }).then(b => {
      // ...
    });
    // Parameterless arrow functions that are visually easier to parse
    setTimeout( () => {
      console.log('I happen sooner');
      setTimeout( () => {
        // deeper code
        console.log('I happen later');
      }, 1);
    }, 1);

    var Foo = () => {};
    var foo = new Foo(); // TypeError: Foo is not a constructor
    console.log(Foo.prototype); // undefined

    // this, inside arrow function (only from parent)
    function Person(){
      this.age = 0;
      setInterval(() => {
        this.age++; // this - refers to the Person object
      }, 1000);
    }

    // predefined parameter value
    function myFunction(x, y = 10) { // y is 10 if not passed or undefined
      return x + y;
    }
    myFunction(5); // will return 15

    // ...restOfArgs parameters - Array of parameters after predefined or all given
    function myFun(a, b, ...restOfArgs) {
      console.log("a", a, "b", b);
      console.log("restOfArgs", restOfArgs);
      var first = restOfArgs.pop(); // gives first rest-argument
    }
    myFun("one", "two", "three", "four", "five", "six");
    // a, one, b, two
    // restOfArgs = [three, four, five, six]
    // restOfArgs.length = 4
    myFun("one", "two");
    // a, one, b, two
    // manyMoreArgs, []

    function multiply(multiplier, ...theArgs) {
      return theArgs.map(element => multiplier * element);
    }
    var arr = multiply(2, 1, 2, 3); // [2, 4, 6]

    function sum(...restOfArgs) {
      return restOfArgs.reduce((previous, current) => {
        return previous + current;
      });
    }
    sum(1, 2, 3); // 6

    // convert arguments to array
    var normalArray = Array.prototype.slice.call(arguments);
    // -- or --
    var normalArray = [].slice.call(arguments);
    // -- or --
    var normalArray = Array.from(arguments);

    // new.target
    function Foo() {
      if (!new.target) throw 'Foo() must be called with new';
    }
    try {
      Foo();
    }
    catch(e) {
      console.log(e); // "Foo() must be called with new"
    }

    function Foo() {
      if (!new.target) throw 'Foo() must be called with new';
      console.log('Foo instantiated with new');
    }
    Foo(); // throws "Foo() must be called with new"
    new Foo(); // logs "Foo instantiated with new"

    class A {
      constructor() {
        console.log(new.target.name);
      }
    }
    class B extends A { constructor() { super(); } }
    var a = new A(); // logs "A"
    var b = new B(); // logs "B"
    class C { constructor() { console.log(new.target); } }
    class D extends C { constructor() { super(); } }
    var c = new C(); // logs class C{constructor(){console.log(new.target);}}
    var d = new D(); // logs class D extends C{constructor(){super();}}
  

Funtion Maps


    var map = {
      functionOne: function(obj) {
        return console.info('I am at functionOne: %o', obj);
      },
      functionTwo: function(obj) {
        return console.info('I am at functionTwo: %o', obj);
      },
      functionThree: function(obj) {
        return console.info('I am at functionThree: %o', obj);
      }
    };

    map.functionOne({foo: 'bar'})

    map[key]({hello: 'World'})

    var arr = data.map(function(item){
      return item[map[key](item)];
    });
  

Destructuring/Rest (ES2015)


    // ARRAY

    var foo = ['one', 'two', 'three'];
    var [one, two, three] = foo; // one="one",two="two",three="three"

    var a, b; // assignment apart from declaration
    [a, b] = [1, 2]; // a=1, b=2

    var a, b;
    [a=5, b=7] = [1]; // a=1(assigned), b=7(from default)

    var a = 1, b = 3;
    [a, b] = [b, a]; // a=3, b=1 - swapped

    function f() { return [1, 2]; }
    var a, b;
    [a, b] = f(); // a=1, b=2 - values from function

    function f() { return [1, 2, 3]; }
    var [a, ,b] = f(); // a=1, b=2 - second value ignored

    [,,] = f(); // ignore all

    var [a, ...b] = [1, 2, 3]; // a=1, b=[2, 3] - rest of array assignment

    // OBJECT

    var o = {p: 42, q: true};
    var {p, q} = o; // p=42, q=true

    var a, b;
    ({a, b} = {a: 1, b: 2}); // asigning without declaration, () - are required

    var o = {p: 42, q: true};
    var {p: foo, q: bar} = o; // foo=42, bar=true - new variables assignment

    var {a = 10, b = 5} = {a: 3}; // a=3(assigned), b=5(from default)

    // invalid JS identifier as a property name
    const foo = { 'fizz-buzz': true };
    const { 'fizz-buzz': fizzBuzz } = foo; // fizzBuzz="true"

    // new variables assignment with defaults
    var {a: aa = 10, b: bb = 5} = {a: 3}; // aa=3, bb=5

    // computed object property names
    let key = 'z';
    let {[key]: foo} = {z: 'bar'}; // foo="bar"

    // nested object and array destructuring
    const employee = {
      id: 007,
      name: 'James',
      dept: {
        id: 'D001',
        name: 'Spy',
        address: {
          street: '30 Wellington Square',
          city: 'Chelsea'
        }
      }
    }
    const { dept: { address } } = employee;
    const { dept: { address: { street } } } = employee;
    // const { name, age=25 } = employee;
    const { name, dept, message = `${name} is ${dept.name}`} = employee;
    console.log(message); // James is Spy

    var metadata = {
      title: 'Scratchpad',
      translations: [
        {
          locale: 'de',
          localization_tags: [],
          last_edit: '2014-04-14T08:43:37',
          url: '/de/docs/Tools/Scratchpad',
          title: 'JavaScript-Umgebung'
        }
      ],
      url: '/en-US/docs/Tools/Scratchpad'
    };
    var {title: englishTitle, translations: [{title: localeTitle}]} = metadata;
    console.log(englishTitle); // "Scratchpad"
    console.log(localeTitle);  // "JavaScript-Umgebung"

    const obj = {
      a: 10,
      b: {
        x: 20,
        y: 30,
        z: 40
      }
    };
    const {b: {x, ...rest1}, ...rest2} = obj;    // no error
    const {...rest, ...rest2} = obj; // SyntaxError: Rest element must be last element

    // for...of loop
    for(let {name, age} of employees) {
      console.log(`${name} is ${age} years old!!!`);
    }
    var people = [
      {
        name: 'Mike Smith',
        family: {
          mother: 'Jane Smith',
          father: 'Harry Smith',
          sister: 'Samantha Smith'
        },
        age: 35
      },
      {
        name: 'Tom Jones',
        family: {
          mother: 'Norah Jones',
          father: 'Richard Jones',
          brother: 'Howard Jones'
        },
        age: 25
      }
    ];
    for (var {name: n, family: {father: f}} of people) {
      console.log('Name: ' + n + ', Father: ' + f);
    }
    // "Name: Mike Smith, Father: Harry Smith"
    // "Name: Tom Jones, Father: Richard Jones"

    // fields from objects passed as function parameter
    function userId({id}) { return id; }
    function whois({displayName, fullName: {firstName: name}}) {
      console.log(displayName + ' is ' + name);
    }
    var user = {
      id: 42,
      displayName: 'jdoe',
      fullName: { firstName: 'John', lastName: 'Doe' }
    };
    console.log('userId: ' + userId(user)); // "userId: 42"
    whois(user); // "jdoe is John"

    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    // x = 1, y = 2, z = {c: 3, d: 4}
    let n = { x, y, ...z };
    n; // { x: 1, y: 2, a: 3, b: 4 }

    // FUNCTION

    // ES2015
    function drawChart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
      console.log(size, cords, radius);
      // ...
    }
    // vs ES5 version
    function drawChart(options) {
      options = options === undefined ? {} : options;
      var size = options.size === undefined ? 'big' : options.size;
      var cords = options.cords === undefined ? {x: 0, y: 0} : options.cords;
      var radius = options.radius === undefined ? 25 : options.radius;
      console.log(size, cords, radius);
      // ...
    }
    // usage
    drawChart({
      cords: {x: 18, y: 30},
      radius: 30
    });
  

Spread (ES2015)


    // FUNCTION calls

    function myFunction(x, y, z) { }
    var args = [0, 1, 2];
    myFunction(...args); // same as: myFunction.apply(null, args);

    function myFunction(v, w, x, y, z, xyz) { }
    var args = [0, 1];
    myFunction(-1, ...args, 2, ...[3]); // filling multiple arguments
    v=-1, w=0, x=1, y=2, z=3, xyz=undefined

    // in ES2015
    var dateFields = [1970, 0, 1];
    var d = new Date(...dateFields); // 1 Jan 1970 - new, with spread syntax
    // vs in ES5
    function applyAndNew(constructor, args) {
      function partial () { return constructor.apply(this, args); };
      if (typeof constructor.prototype === "object") {
        partial.prototype = Object.create(constructor.prototype);
      }
      return partial;
    }
    function myConstructor () {
      console.log("arguments.length: " + arguments.length);
      console.log(arguments);
      this.prop1="val1";
      this.prop2="val2";
    };
    var myArguments = ["hi", "how", "are", "you", "mr", null];
    var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);
    console.log(new myConstructorWithArguments);
    // (internal log of myConstructor):           arguments.length: 6
    // (internal log of myConstructor):           ["hi", "how", "are", "you", "mr", null]
    // (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

    // ARRAY literals

    var parts = ['shoulders', 'knees'];
    var lyrics = ['head', ...parts, 'and', 'toes'];
    // lyrics = ["head","shoulders","knees","and","toes"]

    var arr = [1, 2, 3];
    var arr2 = [...arr]; // array copy, like arr.slice()
    arr2.push(4); // arr2 = [1, 2, 3, 4], arr - remains unaffected

    var arr = [[1], [2], [3]];
    var arr2 = [...arr];
    arr2.shift().shift(); // 1 - extracted from both arrays ! , arr = [[], [2], [3]]

    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    arr1 = [...arr1, ...arr2]; // same as: arr1 = arr1.concat(arr2);

    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    arr1 = [...arr2, ...arr1];
    // arr1 is now [3, 4, 5, 0, 1, 2] - same as: Array.prototype.unshift.apply(arr1, arr2)

    const arr = [4, 6, -1, 3, 10, 4];
    const max = Math.max(...arr); // 10

    // OBJECT literals

    var obj1 = { foo: 'bar', x: 42 };
    var obj2 = { foo: 'baz', y: 13 };

    var clonedObj = { ...obj1 }; // { foo: "bar", x: 42 }
    // altrnative to Object.assign({}, obj1, obj2) but setters and non-enumerable properties are ignored
    var mergedObj = { ...obj1, ...obj2 }; // { foo: "baz", x: 42, y: 13 }

    // spread array of arguments into object literal, with rest parameter
    const merge = ( ...objects ) => ( { ...objects } );
    // { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
    var mergedObj = merge ( obj1, obj2);
    // { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
    var mergedObj = merge ( {}, obj1, obj2);

    // inherited properties are ignored even if they are enumerable:
    const car = { color: 'blue' };
    const car2 = Object.create(car, {
      type: {
        value: 'coupe',
        enumerable: true,
      }
    });
    console.log(car2.color);                      // 'blue'
    console.log(car2.hasOwnProperty('color'));    // false
    console.log(car2.type);                       // 'coupe'
    console.log(car2.hasOwnProperty('type'));     // true
    console.log({...car2});                       // {type: "coupe"}

    // makes a shallow copy of an object,
    // if a property holds an object, only the reference to the object will be copied
    const obj = {x: {y: 10}};
    const copy1 = {...obj};
    const copy2 = {...obj};
    console.log(copy1.x === copy2.x);    // true

    // TypeError: obj is not iterable !!!
    var obj = {'key1': 'value1'};
    var array = [...obj];
  

Classes (ES2015)


    // DECLARATION
    class Rectangle {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
      get area() { // getter
        return this.calcArea();
      }
      calcArea() { // method
        return this.height * this.width;
      }
      static difference(a, b) {
        const dh = a.height - b.height;
        const dw = a.width - b.width;
        return dh+"-"+dw;
      }
    }
    Rectangle.staticWidth = 20; // static class-side property
    Rectangle.prototype.prototypeWidth = 25; // prototype data properties

    const square = new Rectangle(10, 10);
    console.log(square.area); // 100
    const r1 = new Rectangle(7, 3);
    const r2 = new Rectangle(9, 8);
    console.log(Rectangle.difference(r1, r2)); // 2-5

    // EXPRESSION
    let Rectangle = class { // unnamed
      // ...
    };
    console.log(Rectangle.name); // "Rectangle"

    let Rectangle = class Rectangle2 { // named
      //...
    };
    console.log(Rectangle.name); // "Rectangle2"

    // EXTENDING

    // class + class
    class Cat {
      constructor(name) { this.name = name; }
      speak() { console.log(`${this.name} makes a noise.`); }
    }
    class Lion extends Cat {
      speak() {
        super.speak();
        console.log(`${this.name} roars.`);
      }
    }
    let l = new Lion('Fuzzy');
    l.speak(); // Fuzzy makes a noise. // Fuzzy roars.

    // class_function + class
    function Animal (name) { this.name = name; }
    Animal.prototype.speak = function(){console.log(this.name+' makes a noise.');}
    class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } }
    let d = new Dog('Mitzie');
    d.speak(); // Mitzie barks.

    // object + class
    const Animal = {speak(){console.log(this.name+' makes a noise.');}};
    class Dog { constructor(name) { this.name = name; } }
    Object.setPrototypeOf(Dog.prototype, Animal); // required !
    let d = new Dog('Mitzie');
    d.speak(); // Mitzie makes a noise.

    //SPECIES
    class MyArray extends Array {
      // overwrite species to the parent Array constructor
      static get [Symbol.species]() { return Array; }
    }
    let a = new MyArray(1,2,3);
    let mapped = a.map(x => x * x);
    console.log(mapped instanceof MyArray); // false
    console.log(mapped instanceof Array);   // true

    // MIX-INS
    let calculatorMixin = Base => class extends Base {
      calc() { }
    };
    let randomizerMixin = Base => class extends Base {
      randomize() { }
    };

    class Foo { }
    class Bar extends calculatorMixin(randomizerMixin(Foo)) { }
  

Symbol (ES2015)


    var sym1 = Symbol();
    var sym2 = Symbol('foo');
    var sym3 = Symbol('foo');
    Symbol('foo') === Symbol('foo'); // false
    Symbol("foo") !== Symbol("foo")

    var sym = new Symbol(); // TypeError, prevents creating explicit Symbol wrapper object

    // Symbol wrapper object
    var sym = Symbol('foo');
    typeof sym;     // "symbol"
    var symObj = Object(sym);
    typeof symObj;  // "object"

    const foo = Symbol() // typeof foo === "symbol"
    const bar = Symbol() // typeof bar === "symbol"
    let obj = {}
    obj[foo] = "foo"
    obj[bar] = "bar"
    JSON.stringify(obj) // {}
    Object.keys(obj) // []
    Object.getOwnPropertyNames(obj) // []
    Object.getOwnPropertySymbols(obj) // [ Symbol(), Symbol() ]

    const iterable1 = new Object();
    iterable1[Symbol.iterator] = function* () {
      yield 1;
      yield 2;
      yield 3;
    };
    [...iterable1]; // Array [1, 2, 3]

    const regexp1 = /foo/;
    '/foo/'.startsWith(regexp1); // Error, ...can't be a Regular Expression
    regexp1[Symbol.match] = false;
    '/foo/'.startsWith(regexp1); // true
    '/baz/'.endsWith(regexp1); // false

    class ReplSrchSplit {
      constructor(value) {
        this.value = value;
      }
      [Symbol.replace](string) {
        return `s/${string}/${this.value}/g`;
      }
      [Symbol.search](string) {
        return string.indexOf(this.value);
      }
      [Symbol.split](string) {
        var index = string.indexOf(this.value);
        return this.value + string.substr(0, index) + "/"
          + string.substr(index + this.value.length);
      }
    }
    'foo'.replace(new ReplSrchSplit('bar')); // "s/foo/bar/g"
    'foobar'.search(new ReplSrchSplit('bar')); // 3
    'foobar'.split(new ReplSrchSplit('foo')); //"foo/bar"

    class Array1 {
      static [Symbol.hasInstance](instance) {
        return Array.isArray(instance);
      }
    }
    [] instanceof Array1; // true
    // custom instanceof behavior
    class MyArray {
      static [Symbol.hasInstance](instance) {
        return Array.isArray(instance);
      }
    }
    [] instanceof MyArray; // true

    const alpha = ['a', 'b', 'c'];
    const numeric = [1, 2, 3];
    let alphaNumeric = alpha.concat(numeric);
    alphaNumeric; // Array ["a", "b", "c", 1, 2, 3]
    numeric[Symbol.isConcatSpreadable] = false;
    alphaNumeric = alpha.concat(numeric);
    alphaNumeric; // Array ["a", "b", "c", Array [1, 2, 3]]

    var x = [1, 2, 3];
    var fakeArray = {
      [Symbol.isConcatSpreadable]: true,
      length: 2, // control the number of object properties to be added
      0: 'hello',
      1: 'world'
    }

    const object1 = {
      property1: 42
    };
    object1[Symbol.unscopables] = {
      property1: true
    };
    with (object1) {
      console.log(property1); // Error: property1 is not defined
    }

    class Array1 extends Array {
      static get [Symbol.species]() { return Array; }
    }
    const a = new Array1(1, 2, 3);
    const mapped = a.map(x => x * x);
    mapped instanceof Array1; // false
    mapped instanceof Array; // true

    const object1 = {
      [Symbol.toPrimitive](hint) {
        if (hint == 'number') {
          return 10;
        }
        if (hint == 'string') {
          return 'hello';
        }
        return true;
      }
    };
    +obj2;     // 10        -- hint is "number"
    `${obj2}`; // "hello"   -- hint is "string"
    obj2 + ''; // "true"    -- hint is "default"

    class ValidatorClass {
      get [Symbol.toStringTag]() {
        return 'Validator';
      }
    }
    Object.prototype.toString.call(new ValidatorClass()); // "[object Validator]"
    // vs standart tags
    Object.prototype.toString.call('foo');     // "[object String]"
    Object.prototype.toString.call([1, 2]);    // "[object Array]"
    Object.prototype.toString.call(new Map());       // "[object Map]"
    Object.prototype.toString.call(function* () {}); // "[object GeneratorFunction]"
    Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"

    Symbol.for('foo'); // create a new global symbol
    Symbol.for('foo'); // retrieve the already created symbol
    // Same global symbol, but not locally
    Symbol.for('bar') === Symbol.for('bar'); // true
    Symbol('bar') === Symbol('bar'); // false
    // The key is also used as the description
    var sym = Symbol.for('mario');
    sym.toString(); // "Symbol(mario)"

    // prefix your symbols to avoid name clashes with global symbol
    Symbol.for('mdn.foo');
    Symbol.for('mdn.bar');

    Symbol.for('bar') === Symbol.for('bar'); // true
    Symbol('bar') === Symbol('bar'); // false
    const symbol1 = Symbol.for('foo');
    symbol1.toString(); // "Symbol(foo)"

    const globalSym = Symbol.for('foo'); // global symbol
    Symbol.keyFor(globalSym); //  "foo"
    const localSym = Symbol(); // local symbol
    Symbol.keyFor(localSym); // undefined
    Symbol.keyFor(Symbol.iterator); // undefined

    Symbol.keyFor(Symbol.for("tokenString")) == "tokenString"; // true
  

Type Conversion


    // Unary + Operator
    var y = "5";      // y is a string - "5"
    var x = + y;      // x is a number -  5

    var y = "John";   // y is a string
    var x = + y;      // x is a number (NaN)

    5 + null    // returns 5         because null is converted to 0
    "5" + null  // returns "5null"   because null is converted to "null"
    "5" + 2     // returns "52"      because 2 is converted to "2"
    "5" - 2     // returns 3         because "5" is converted to 5
    "5" * "2"   // returns 10        because "5" and "2" are converted to 5 and 2

    document.getElementById("demo").innerHTML = myVar; // =>
    // if myVar = {name:"Fjohn"}  // toString converts to "[object Object]"
    // if myVar = [1,2,3,4]       // toString converts to "1,2,3,4"
    // if myVar = new Date()      // toString converts to "Fri Jul 18 2018 09:08:55 GMT+0200"
    // if myVar = 123             // toString converts to "123"
    // if myVar = true            // toString converts to "true"
    // if myVar = false           // toString converts to "false"
  
Original Value Converted to Number
Number(x)
Converted to String
String(x)
Converted to Boolean
Boolean(x)
false 0 "false" false
true 1 "true" true
0 0 "0" false
1 1 "1" true
"0" 0 "0" true
"000" 0 "000" true
"1" 1 "1" true
NaN NaN "NaN" false
Infinity Infinity "Infinity" true
-Infinity -Infinity "-Infinity" true
"" 0 "" false
"20" 20 "20" true
"twenty" NaN "twenty" true
[ ] 0 "" true
[20] 20 "20" true
[10,20] NaN "10,20" true
["twenty"] NaN "twenty" true
["ten","twenty"] NaN "ten,twenty" true
function(){} NaN "function(){}" true
{ } NaN "[object Object]" true
null 0 "null" false
undefined NaN "undefined" false

Bitwise Operations

Operator Name Returns Operation Result Same as Result
& AND 1 only if both bits are 1 5 & 1 1 0101 & 0001 0001
| OR 1 if one of the bits are 1 5 | 1 5 0101 | 0001 0101
^ XOR 1 if the bits are different 5 ^ 1 4 0101 ^ 0001 0100
~ NOT inverts all the bits ~ 5 10 ~0101 1010
<< Zero fill left shift Shifts left by pushing zeros in from the right and let the leftmost bits fall off 5 << 1 10 0101 << 1 1010
>> Signed right shift Shifts right by pushing copies of the leftmost bit in from the left, and let the rightmost bits fall off 5 >> 1 2 0101 >> 1 0010
>>> Zero fill right shift Shifts right by pushing zeros in from the left, and let the rightmost bits fall off 5 >>> 1 2 0101 >>> 1 0010

    // Decimal to Binary
    function dec2bin(dec){
      return (dec >>> 0).toString(2);
    }

    // Binary to Decimal
    function bin2dec(bin){
      return parseInt(bin, 2).toString(10);
    }
  

/regexp/g


    var str = "The rain in Spain stays mainly in the plain";

    var n = str.search("Spain"); // = 6 , case-sensitive
    var n = str.search(/spain/i); // = 6 , case-insensitive

    var res = str.replace("Spain", "Italy");
    var res = str.replace(/spain/i, "Italy");

    // replaceAll(searchValue, replaceValue) (ES2021)
    const queryString = 'q=query+string+parameters';
    const withSpaces = queryString.replaceAll('+', ' ');

    // test()
    var patt = /e/;
    patt.test(str); // true
    /e/.test(str); // true

    // exec() - search and return found OR null
    /e/.exec(str);

    var patt = /ain/gi; // global and ignore case modifiers are set, multiline - not
    var res = patt.global; // true
    var res = patt.ignoreCase; // true
    var res = patt.multiline; // false
    var res = "The text of the RegExp is: " + patt.source;

    while (patt1.test(str) == true) {
      document.write("'ain' found. Index now at: " + patt1.lastIndex + ", ");
    }
    // 'ain' found. Index now at: 8
    // 'ain' found. Index now at: 17
    // 'ain' found. Index now at: 28
    // 'ain' found. Index now at: 43

    // --- unicode (ES2018)
    const regexGreekSymbol = /\p{Script=Greek}/u;
    regexGreekSymbol.test('π'); // true

    // --- s flag (dotAll) (ES2018)
    // matches any character except line break characters (like \n) or carriage return (\r)
    // find a character that's either a digit (\d) or a non-digit (\D)
    console.log(/one[\d\D]two/.test('one\ntwo'));// true (before ES2018)
    console.log(/one.two/.test('one\ntwo'));     // false
    console.log(/one.two/s.test('one\ntwo'));    // true (ES2018)

    // --- named capture groups (ES2018)
    // capture group can be given a name using the (?<name>...) syntax, for any identifier name
    let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
    let result = re.exec('2015-01-02');
    // result.groups.year === '2015';
    // result.groups.month === '01';
    // result.groups.day === '02';
    // result[0] === '2015-01-02';
    // result[1] === '2015';
    // result[2] === '01';
    // result[3] === '02';
    // with destructuring
    let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
    console.log(`one: ${one}, two: ${two}`);  // prints one: foo, two: bar
    // backreferences
    // accessed within a regular expression via the \k<name> construct
    let duplicate = /^(?<half>.*).\k<half>$/u;
    duplicate.test('a*b'); // false
    duplicate.test('a*a'); // true
    // simultaneously with numbered references
    let triplicate = /^(?<part>.*).\k<part>.\1$/u;
    triplicate.test('a*a*a'); // true
    triplicate.test('a*a*b'); // false
    // replacement targets
    // named groups can be referenced from the replacement value passed to String.prototype.replace too
    // if the value is a string, named groups can be accessed using the $<name> syntax
    let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
    let result = '2015-01-02'.replace(re, '$<day>/$<month>/$<year>');
    // result === '02/01/2015'
    // ordinary string literal, not a template literal, is passed into replace,
    // that method will resolve the values of day etc rather than having them as local variables
    // if the second argument to String.prototype.replace is a function,
    // then the named groups can be accessed via a new parameter called groups
    // new signature would be function (matched, capture1, ..., captureN, position, S, groups)
    // named captures would still participate in numbering, as usual
    let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
    let result = '2015-01-02'.replace(re, (...args) => {
      let {day, month, year} = args[args.length - 1];
      return `${day}/${month}/${year}`;
    });
    // result === '02/01/2015'

    // --- lookbehind assertions (ES2018)
    // denoted by (?&lt;=...), and enables to match a pattern based on the substring that precedes the pattern
    /(?<=\$)\d+(\.\d*)?/  // matching '$10.53' and returning '10.53',  would not match €10.53
    /(?<!\$)\d+(?:\.\d*)/ // would not match '$10.53', but would '€10.53'
    const re = /(?&lt;=\$|£|€)\d+(\.\d*)?/;
    console.log(re.exec('199')); // null
    console.log(re.exec('$199')); // ["199", undefined, index: 1, input: "$199", groups: undefined]
    console.log(re.exec('€50')); // ["50", undefined, index: 1, input: "€50", groups: undefined]
  

try{}catch(){}finnally{}


    try {
      // Block of code to try
    }
    catch(error_object) {
      // Block of code to handle errors
      // error_object.name
      // error_object.message
    }
    finally {
      // Block of code to be executed regardless of the try / catch result
    }

    try {
      adddlert("Welcome guest!");
    }
    catch(error_object) {
      document.getElementById("demo").innerHTML = error_object.message;
    }
    // error_object.message = adddlert is not defined
    // => TypeError: snhb.startAuction is not a function

    try {
      if(x == "") throw "is empty";
      if(isNaN(x)) throw "is not a number";
      x = Number(x);
      if(x > 10) throw "is too high";
      if(x < 5) throw "is too low";
    }
    catch(error_object) {
      message.innerHTML = "Error: " + error_object + ".";
    }
    finally {
      document.getElementById("demo").value = "";
    }

    // --- omitting catch binding and its surrounding parentheses (ES2018)
    try {
      let parsed = JSON.parse(obj)
    } catch {
      console.log(obj)
    }

    // --- rethrowing an error with a cause (ES2022)
    try {
      frameworkThatCanThrow();
    } catch (err) {
      throw new Error('New error message', { cause: err });
    }
  

"use strict";


    "use strict";
    // errors statements
    x = 3.14;
    y = {p1:10, p2:20};
    var z = "z_value"; delete z;
    function fnc(p1, p2) {}; delete fnc;
    function x(p1, p1) {};
    var x = 010;
    var x = "\010";

    var obj = {};
    Object.defineProperty(obj, "x", {value:0, writable:false});
    obj.x = 3.14;            // => error

    Object.defineProperty(obj, "y", {value:0, writable:false});
    obj.y = 3.14;            // => error

    delete Object.prototype; // undeletable property

    var eval = 3.14;
    var arguments = 3.14;
    var protected = 3.14;

    with (Math){x = cos(2)};

    eval ("var x = 2");
    alert (x);

    myFunction();
    function myFunction() {
      y = 3.14;   // This will also cause an error because y is not declared
    }

    // --- inside non-strict script
    x = 3.14;     // This will not cause an error.
    myFunction();
    function myFunction() {
      "use strict";
      y = 3.14;   // This will cause an error
    }
  

this. / super()


    var person = { // owner of iiner function
      firstName: "John",
      lastName : "Doe",
      id       : 5566,
      fullName : function() {
        return this.firstName + " " + this.lastName; // this = person-object
      }
    };

    var person1 = {
      fullName: function() {
        return this.firstName + " " + this.lastName;
      }
    }
    var person2 = {
      firstName:"John",
      lastName: "Doe"
    }
    person1.fullName.call(person2);  // Will return "John Doe"

    function Person() {
      var that = this;
      that.age = 0;
      setInterval(function growUp() {
        that.age++;
      }, 1000);
    }

    // super([arguments]); // calls the parent constructor.
    // super.functionOnParent([arguments]);
    class Rectangle {
      constructor(height, width) {
        this.name = 'Rectangle';
        this.height = height;
        this.width = width;
      }
      sayName(){console.log('Hi, I am a ', this.name + '.');}
      get area(){return this.height*this.width;}
      set area(value){this.height=this.width=Math.sqrt(value);}
    }
    class Square extends Rectangle {
      constructor(length) {
        this.height; // ReferenceError ! super needs to be called first !
        super(length, length); // calls parent with provided width and height
        this.name = 'Square';
      }
    }
    // super in static method
    class Rectangle {
      constructor() {}
      static logNbSides() { return 'I have 4 sides'; }
    }
    class Square extends Rectangle {
      constructor() {}
      static logDescription() { return super.logNbSides() + ' which are all equal'; }
    }
    Square.logDescription(); // I have 4 sides which are all equal
  

    // with globalThis available,
    // additional search for the global across environments is not necessary anymore
    if (typeof globalThis.setTimeout !== 'function') {
      // no setTimeout in this environment!
    }

    // prior to globalThis
    var getGlobal = function () {
      if (typeof self !== 'undefined') { return self; }
      if (typeof window !== 'undefined') { return window; }
      if (typeof global !== 'undefined') { return global; }
      throw new Error('unable to locate global object');
    };
    var globals = getGlobal();
    if (typeof globals.setTimeout !== 'function') {
      // no setTimeout in this environment!
    }
  

Scope,var,let,const

Scope

Hoisting

let, const


    var carName = "Volvo";    // Global scope
    // code here can use window.carName

    let carOwner = "Volvo";   // Global scope
    // code here can NOT use window.carOwner

    function myFunction2() {
      var carName = "Volvo";  // Function Scope
    }
    function myFunction2() {
      let carName = "Volvo";  // Function Scope
    }

    // you can start using here var-variable, but not let/const-variables
    var x = 2;    // Allowed
    var x = 3;    // Allowed
    x = 4;        // Allowed
    let x = 3;    // Not allowed (redeclaring var with let)
    const x = 7;  // Not allowed (redeclaring var with const)
    let y = 5;    // Allowed
    let y = 7;    // Not allowed (redeclaring let with let)
    const y = 7;  // Not allowed (redeclaring let with const)
    var y = 9;    // Not allowed (redeclaring let with var)
    const z = 12; // Allowed
    const z = 15; // Not allowed (redeclaring const)
    z = 15; // Not allowed (redeclaring const)
    var z = 4;  // Not allowed (redeclaring const with var)
    let z = 5;  // Not allowed (redeclaring const with let)
    {
      var x = 4;  // Allowed (declaring same-name var in another scope)
      let x = 5;  // Not allowed (redeclaring var with let)
      const x = 5;  // Not allowed (redeclaring var with const)
      let y = 4;  // Allowed (declaring same-name let in another scope)
      var y = 5;  // Not allowed (redeclaring let with var)
      const y = 7;// Not allowed (redeclaring let with const)
      const z = 12; // Allowed (declaring same-name const in another scope)
      z = 15; // Not allowed (redeclaring const)
      var z = 4;  // Not allowed (redeclaring const with var)
      let z = 5;  // Not allowed (redeclaring const with let)
    }

    const PI = 3.141592653589793;
    PI = 3.14;      // This will give an error
    PI = PI + 10;   // This will also give an error

    // create a constant object:
    const car = {type:"Fiat", model:"500", color:"white"};
    car.color = "red"; // Allowed - change a property
    car.owner = "Johnson"; // Allowed - add a property
    car = {type:"Volvo", model:"EX60", color:"red"}; // Not allowed - reassign a constant object

    // create a constant array:
    const cars = ["Saab", "Volvo", "BMW"];
    cars[0] = "Toyota"; // Allowed - change an element
    cars.push("Audi"); // Allowed - add an element
    cars = ["Toyota", "Volvo", "Audi"]; // Not allowed - reassign a constant array

    // ---------------

    // code here can use carName and not carOwner or carType
    var carName = "Volvo"; // global variable
    // code here can use carName and not carOwner or carType
    function myFunction() {
      // code here can use carName and not carOwner or carType
      var carOwner = "Volvo"; // local scope
      const carType = "sedan";
      // code here can use carName, carOwner and carType
    }
    // code here can use carName and not carOwner or carType

    // ---------------

    var x = 10; // 10
    var y = 20; // 20
    var z = 30; // 30
    {
      var x = 1; // global scope variable
      let y = 2; // local scope variable
      const z = 3; // local scope variable
      let own_let = 2;
    }
    // Here x is 1
    // Here y is 20
    // Here z is 30
    // own_let can NOT be used here

    // ---------------

    var i = 5;
    for (var i = 0; i < 10; i++) {
      // some statements
    }
    // Here i is 10

    let i = 5;
    for (let i = 0; i < 10; i++) {
      // some statements
    }
    // Here i is 5
  

JSON


    var JD = {"firstName":"John", "lastName":"Doe"};
    for (info in JD) {
      // JD.info;
    }

    var e_obj = {
      "employees":[
        {
          "name":"John",
          "age":32,
          "cars": [
            { "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
            { "name":"BMW", "models":[ "320", "X3", "X5" ] },
            { "name":"Fiat", "models":[ "500", "Panda" ] }
          ]
        },
        {"firstName":"Anna", "cars": []},
        {"firstName":"Peter", "cars": []}
      ]
    };

    for (emp_index in e_obj.employees) {
      // e_obj.employees[emp_index].name
      for (car_index in e_obj.employees[emp_index].cars) {
        // e_obj.employees[emp_index].cars[car_index].name
        for (model_index in e_obj.employees[emp_index].cars[car_index].models) {
            // e_obj.employees[emp_index].cars[car_index].models[model_index]
        }
      }
    }

    var e_obj_str = JSON.stringify(e_obj); // '{ "employees" : [{ "name":"John" , ...
    var e_obj_str = JSON.stringify([1,2,3]); // '[1,2,3]'
    var e_obj_str = JSON.stringify({ d: new Date() }); // '{"d":"2018-10-07T14:21:52.507Z"}'
    var e_obj_str = JSON.stringify({ fn: function () {return 30;} }); // '{"fn":"function () {return 30;}"}'
    // OR
    obj.fn = obj.fn.toString();

    var obj = JSON.parse(e_obj_str); // convert json-stringback  to json-object

    obj.employees[1].name; // Anna
    obj.employees[1]['name']; // Anna
    obj.employees[1].name = 'A.'; // Anna -> A.

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var myObj = JSON.parse(this.responseText);
        // when responseText is { "name":"John",  "age":"function () {return 32;}", "birth":"1986-09-14",...}
        myObj.name + ": " + new Date(myObj.birth);
        // parsing function
        obj.age = eval("(" + myObj.age + ")");
        obj.age() // 32
        // parsing date with reviver parameter
        var obj = JSON.parse(text, function (key, value) {
        if (key == "birth") {
          return new Date(value);
        } else {
          return value;
        }});
        // when responseText is [ "Ford", "BMW", "Audi", "Fiat" ]
        myArr[0];
      }
    };
    xmlhttp.open("POST", "json_demo.txt", true);
    xmlhttp.send();
  
  
    header("Content-Type: application/json; charset=UTF-8");
    $obj = json_decode($_POST["x"], false);
    $conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");
    $stmt = $conn->prepare("SELECT name FROM ? LIMIT ?");
    $stmt->bind_param("ss", $obj->table, $obj->limit);
    $stmt->execute();
    $result = $stmt->get_result();
    $outp = $result->fetch_all(MYSQLI_ASSOC);
    exit(json_encode($outp));
  

JSONP

  
    <script src="demo_jsonp.php">
  

or for dinamyc usage

  
    <?php
      header("Content-Type: application/json; charset=UTF-8");
      $obj = json_decode($_GET["x"], false);
      $conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");
      $result = $conn->query("SELECT name FROM ".$obj->$table." LIMIT ".$obj->$limit);
      $outp = array();
      $outp = $result->fetch_all(MYSQLI_ASSOC);
      echo "myFunc(".json_encode($outp).")";
    ?>
  

    function clickButton() {
      var obj, s
      obj = { table: "products", limit: 10 };
      s = document.createElement("script");
      s.src = "jsonp_demo_db.php?x=" + JSON.stringify(obj);
      document.body.appendChild(s);
    }
    function myFunc(myObj) {
      var x, txt = "";
      for (x in myObj) {
          txt += myObj[x].name;
      }
      document.getElementById("demo").innerHTML = txt;
    }
  

Proxy (ES2015)


    var p = new Proxy(target, handler);

    // unexistent properties handling
    var handler = {
      get: function(obj, prop) { return prop in obj ? obj[prop] : 37; }
    };
    var p = new Proxy({}, handler);
    p.a = 1;
    p.b = undefined;
    console.log(p.a, p.b); // 1, undefined
    console.log('c' in p, p.c); // false, 37

    // No-op forwarding proxy
    var target = {};
    var p = new Proxy(target, {});
    p.a = 37;               // operation forwarded to the target
    console.log(target.a);  // 37. The operation has been properly forwarded

    // complete traps list example
    var docCookies = new Proxy(docCookies, {
      get: function (oTarget, sKey) {           // trap for getting property values
        return oTarget[sKey] || oTarget.getItem(sKey) || undefined;
      },
      set: function (oTarget, sKey, vValue) {   // trap for setting property values
        if (sKey in oTarget) { return false; }
        return oTarget.setItem(sKey, vValue);
      },
      deleteProperty: function (oTarget, sKey) {  // trap for the delete operator
        if (sKey in oTarget) { return false; }
        return oTarget.removeItem(sKey);
      },
      enumerate: function (oTarget, sKey) { return oTarget.keys(); },
      // trap for .getOwnPropertyNames and .getOwnPropertySymbols
      ownKeys: function (oTarget, sKey) { return oTarget.keys(); },
      has: function (oTarget, sKey) { return sKey in oTarget || oTarget.hasItem(sKey); },
      defineProperty: function (oTarget, sKey, oDesc) { // trap for Object.defineProperty
        if (oDesc && 'value' in oDesc) { oTarget.setItem(sKey, oDesc.value); }
        return oTarget;
      },
      getOwnPropertyDescriptor: function (oTarget, sKey) {
        var vValue = oTarget.getItem(sKey);
        return vValue ? {
          value: vValue,
          writable: true,
          enumerable: true,
          configurable: false
        } : undefined;
      },
      // trap for new-operator
      construct: function(target, argumentsList, newTarget) { }
      // trap for a function call
      apply: function(target, thisArg, argumentsList) { }
      // trap for Object.isExtensible
      isExtensible: function(target) { }
      // trap for Object.preventExtensions
      preventExtensions: function(target) { }
      has: function(target, prop) { }, // trap for the in-operator
    });
    console.log(docCookies.my_cookie1 = 'First value');
    console.log(docCookies.getItem('my_cookie1'));
    docCookies.setItem('my_cookie1', 'Changed value');
    console.log(docCookies.my_cookie1);

    // Proxy.revocable() - turn off proxy
    var revocable = Proxy.revocable(
      {},
      { get: function(target, name) { return "[[" + name + "]]"; } }
    );
    var proxy = revocable.proxy;
    console.log(proxy.foo); // "[[foo]]"
    revocable.revoke();
    console.log(proxy.foo); // TypeError is thrown
    proxy.foo = 1           // TypeError again
    delete proxy.foo;       // still TypeError
    typeof proxy            // "object", typeof doesn't trigger any trap

    // validation
    let validator = {
      set: function(obj, prop, value) {
        if (prop === 'age') {
          if (!Number.isInteger(value)) {
            throw new TypeError('The age is not an integer'); }
          if (value > 200) {
            throw new RangeError('The age seems invalid'); }
        }
        obj[prop] = value; // The default behavior to store the value
        return true; // Indicate success
      }
    };
    let person = new Proxy({}, validator);
    person.age = 100;
    console.log(person.age); // 100
    person.age = 'young'; // Throws an exception
    person.age = 300; // Throws an exception

    // extending constructor
    function extend(super_class, target_class) {
      var descriptor = Object.getOwnPropertyDescriptor(
        target_class.prototype,
        'constructor'
      );
      target_class.prototype = Object.create(super_class.prototype);
      var handler = {
        construct: function(target, args) {
          var obj = Object.create(target_class.prototype);
          this.apply(target, obj, args);
          return obj;
        },
        apply: function(target, that, args) {
          super_class.apply(that, args);
          target_class.apply(that, args);
        }
      };
      var proxy = new Proxy(target_class, handler);
      descriptor.value = proxy;
      Object.defineProperty(target_class.prototype, 'constructor', descriptor);
      return proxy;
    }
    var Person = function(name) { this.name = name; };
    var Boy = extend(Person, function(name, age) { this.age = age; });
    Boy.prototype.sex = 'M';
    var Peter = new Boy('Peter', 13);
    console.log(Peter.sex);  // "M"
    console.log(Peter.name); // "Peter"
    console.log(Peter.age);  // 13

    // toggle the attribute or class name of two different elements
    let view = new Proxy( { selected: null } , {
      set: function(obj, prop, newval) {
        let oldval = obj[prop];
        if (prop === 'selected') {
          if (oldval) { oldval.setAttribute('aria-selected', 'false'); }
          if (newval) { newval.setAttribute('aria-selected', 'true'); }
        }
        obj[prop] = newval; // default behavior to store the value
        return true; // success
      }
    });
    let i1 = view.selected = document.getElementById('item-1'); // i1.getAttribute('aria-selected') = 'true'
    let i2 = view.selected = document.getElementById('item-2');
    console.log(i1.getAttribute('aria-selected')); // 'false'
    console.log(i2.getAttribute('aria-selected')); // 'true'

    // value correction and an extra property
    let products = new Proxy( { browsers: ['Internet Explorer', 'Netscape'] } , {
      get: function(obj, prop) {
        if (prop === 'latestBrowser') { return obj.browsers[obj.browsers.length - 1]; } // extra property
        return obj[prop]; // default behavior to return the value
      },
      set: function(obj, prop, value) {
        if (prop === 'latestBrowser') { obj.browsers.push(value); return true; } // extra property
        if (typeof value === 'string') { value = [value]; } // convert the value if it is not an array
        obj[prop] = value; // default behavior to store the value
        return true; // indicate success
      }
    });
    console.log(products.browsers); // ['Internet Explorer', 'Netscape']
    products.browsers = 'Firefox'; // pass a string (by mistake)
    console.log(products.browsers); // ['Firefox'] - no problem, the value is an array
    products.latestBrowser = 'Chrome';
    console.log(products.browsers); // ['Firefox', 'Chrome']
    console.log(products.latestBrowser); // 'Chrome'

    // finding an array item object by its property
    let products = new Proxy([{name:'Firefox',type:'browser'},{name:'SeaMonkey',type:'browser'}],{
    get: function(obj, prop) {
      if (prop in obj) { return obj[prop]; } // default behavior to return the value by integer
      if (prop === 'number') { return obj.length; } // number of products; an alias of products.length
      let result, types = {};
      for (let product of obj) {
        if (product.name === prop) { result = product; }
        if (types[product.type]) { types[product.type].push(product); }
        else { types[product.type] = [product]; }
      }
      if (result) { return result; } // Get a product by name
      if (prop in types) { return types[prop]; } // Get products by type
      if (prop === 'types') { return Object.keys(types); } // Get product types
      return undefined;
    }});
    console.log(products[0]); // { name: 'Firefox', type: 'browser' }
    console.log(products['Firefox']); // { name: 'Firefox', type: 'browser' }
    console.log(products['Chrome']); // undefined
    console.log(products.browser); // [{name:'Firefox',type:'browser'},{name:'SeaMonkey',type:'browser'}]
    console.log(products.types); // ['browser', 'mailer']
    console.log(products.number); // 3
  

Reflect (ES2015)


    // Reflect.apply(target, thisArgument, argumentsList)
    // calling the given target function with the specified this value and arguments
    console.log(Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111])); // "hello"
    console.log(Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index); // 4
    console.log(Reflect.apply(''.charAt, 'ponies', [3])); // "i"
    // same as Function.prototype.apply.call(Math.floor, undefined, [1.75]);
    console.log(Reflect.apply(Math.floor, undefined, [1.75])); // 1

    // Reflect.construct(target, argumentsList[, newTarget]) - like the new operator, but a function
    // equivalent to calling: new target(...args)
    function func1(a, b, c) { this.sum = a + b + c; }
    const args = [1, 2, 3];
    const object1 = new func1(...args);
    const object2 = Reflect.construct(func1, args);
    console.log(object2.sum); // 6
    console.log(object1.sum); // 6

    const object1 = {};

    // Reflect.defineProperty(target, propertyKey, attributes)
    // like Object.defineProperty() but returns a Boolean
    if (Reflect.defineProperty(object1, 'property1', {value: 42})) {
      console.log('property1 created!'); // "property1 created!"
    } else {
      console.log('problem creating property1');
    }
    console.log(object1.property1); // 42

    // Reflect.set() - works like setting a property on an object
    Reflect.set(object1, 'property1', 42);
    console.log(object1.property1); // 42
    const array1 = ['duck', 'duck', 'duck'];
    Reflect.set(array1, 2, 'goose');
    console.log(array1[2]); //  "goose"

    // Reflect.get(target, propertyKey[, receiver])
    // getting a property from an object (target[propertyKey]) like a function
    const object1 = { x: 1, y: 2 };
    console.log(Reflect.get(object1, 'x')); // 1
    var array1 = ['zero', 'one'];
    console.log(Reflect.get(array1, 1)); // "one"

    // Reflect.ownKeys() - returns an array of the target object's own property keys
    // equivalent to Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
    const object1 = { property1: 42, property2: 13 };
    var array1 = [];
    console.log(Reflect.ownKeys(object1)); // ["property1", "property2"]
    console.log(Reflect.ownKeys(array1)); // ["length"]

    // Reflect.deleteProperty(target, propertyKey)
    // delete properties, like the delete-operator as a function
    // returns; true - if no such property exists, false - if a property is unconfigurable
    Reflect.deleteProperty(object1, 'property1'); // object1.property1 = undefined
    var array1 = [1, 2, 3, 4, 5];
    Reflect.deleteProperty(array1, '3'); // array1 = [1, 2, 3, , 5]

    // Reflect.has(target, propertyKey) - works like the in-operator as a function
    console.log(Reflect.has(object1, 'property1')); // true
    console.log(Reflect.has(object1, 'property2')); // false
    console.log(Reflect.has(object1, 'toString')); // true

    // Reflect.getOwnPropertyDescriptor() - similar to Object.getOwnPropertyDescriptor()
    // returns a property descriptor of the property if it exists OR undefined
    const object1 = { property1: 42 };
    console.log(Reflect.getOwnPropertyDescriptor(object1, 'property1').value); // 42
    console.log(Reflect.getOwnPropertyDescriptor(object1, 'property2')); // undefined
    console.log(Reflect.getOwnPropertyDescriptor(object1, 'property1').writable); // true
    Reflect.getOwnPropertyDescriptor({x: 'hello'}, 'x');
    // {value: "hello", writable: true, enumerable: true, configurable: true}
    Reflect.getOwnPropertyDescriptor({x: 'hello'}, 'y'); // undefined
    Reflect.getOwnPropertyDescriptor([], 'length');
    // {value: 0, writable: true, enumerable: false, configurable: false}

    // Reflect.getPrototypeOf(target) - almost the same method as Object.getPrototypeOf()
    const proto1 = Reflect.getPrototypeOf(object1);
    console.log(proto1); // object Object]
    console.log(Reflect.getPrototypeOf(proto1)); // null

    // Reflect.setPrototypeOf() - same method as Object.setPrototypeOf()
    // sets the prototype of a specified object to another object or to null
    console.log(Reflect.setPrototypeOf(object1, Object.prototype)); //  true
    console.log(Reflect.setPrototypeOf(object1, null)); // true
    const object2 = {};
    console.log(Reflect.setPrototypeOf(Object.freeze(object2), null)); // false

    // Reflect.preventExtensions() , Reflect.isExtensible(target)
    console.log(Reflect.isExtensible(object1)); // true
    Reflect.preventExtensions(object1);
    console.log(Reflect.isExtensible(object1)); // false
    const object2 = Object.seal({});
    console.log(Reflect.isExtensible(object2)); // false
  

Map, Set (ES2015)


    // Map([iterable])
    var myMap = new Map();
    var keyString = 'a string',
        keyObj = {},
        keyFunc = function() {};
    // setting the values
    myMap.set(keyString, "value associated with 'a string'");
    myMap.set(keyObj, 'value associated with keyObj');
    myMap.set(keyFunc, 'value associated with keyFunc');
    myMap.size; // 3
    // getting the values
    myMap.get(keyString);    // "value associated with 'a string'"
    myMap.get(keyObj);       // "value associated with keyObj"
    myMap.get(keyFunc);      // "value associated with keyFunc"
    myMap.get('a string');   // "value associated with 'a string'"
                             // because keyString === 'a string'
    myMap.get({});           // undefined, because keyObj !== {}
    myMap.get(function() {}) // undefined, because keyFunc !== function () {}

    // WeakMap([iterable])
    class ClearableWeakMap {
      constructor(init) { this._wm = new WeakMap(init) }
      clear() { this._wm = new WeakMap() }
      delete(k) { return this._wm.delete(k) }
      get(k) { return this._wm.get(k) }
      has(k) { return this._wm.has(k) }
      set(k, v) { this._wm.set(k, v); return this; }
    }
    // private data and methods belong inside the object and are stored in the privates WeakMap object
    // everything exposed on the instance and prototype is public
    // everything else is inaccessible from the outside world
    // because privates is not exported from the module
    const privates = new WeakMap();
    function Public() {
      const me = { /* private data goes here */ };
      privates.set(this, me);
    }
    Public.prototype.method = function() {
      const me = privates.get(this);
      // do work with 'me'...
    };
    module.exports = Public;

    // Set([iterable])
    var mySet = new Set();
    mySet.add(1); // Set [ 1 ]
    mySet.add(5); // Set [ 1, 5 ]
    mySet.add(5); // Set [ 1, 5 ]
    mySet.add('some text'); // Set [ 1, 5, 'some text' ]
    var o = {a: 1, b: 2};
    mySet.add(o);
    mySet.add({a: 1, b: 2}); // o is referencing a different object so this is okay
    mySet.has(1); // true
    mySet.has(3); // false, 3 has not been added to the set
    mySet.has(5);              // true
    mySet.has(Math.sqrt(25));  // true
    mySet.has('Some Text'.toLowerCase()); // true
    mySet.has(o); // true
    mySet.size; // 5
    mySet.delete(5); // removes 5 from the set
    mySet.has(5);    // false, 5 has been removed
    mySet.size; // 4, we just removed one value
    console.log(mySet);// Set [ 1, "some text", Object {a: 1, b: 2}, Object {a: 1, b: 2} ]

    // WeakSet([iterable])
    var ws = new WeakSet();
    var window = {};
    var foo = {};
    ws.add(window);
    ws.add(obj);
    ws.has(window); // true
    ws.has(foo);    // false, foo has not been added to the set
    ws.delete(window); // removes window from the set
    ws.has(window);    // false, window has been removed
  

Promise (ES2015)


    const myFirstPromise = new Promise((resolve, reject) => {
      // do something asynchronous which eventually calls either:
      // resolve(someValue); // fulfilled
      // OR reject("failure reason"); // rejected
    });

    let myFirstPromise = new Promise((resolve, reject) => {
      // call resolve(...) when what we were doing asynchronously was successful
      // and reject(...) when it failed
      setTimeout(function(){ // simulate async code, in reality: XHR or an HTML5 API
        resolve("Success!"); // Yay! Everything went well!
      }, 250);
    });
    myFirstPromise.then((successMessage) => {
      // successMessage is whatever we passed in the resolve(...) function above
      // doesn't have to be a string, but if it is only a succeed message, it probably will be
      console.log("Yay! " + successMessage);
    });

    function imgLoad(url) {
      return new Promise(function(resolve, reject) {
        var request = new XMLHttpRequest();
        request.open('GET', url);
        request.responseType = 'blob';
        request.onload = function() { // check request loading
          if (request.status === 200) {
            resolve(request.response); // passing back the request response
          } else {
            reject(Error('Image load error, code:' + request.statusText)); // reject the promise
          }
        };
        request.onerror = function() { // entire request fails
            reject(Error('There was a network error.')); // probably a network error
        };
        request.send(); // send the request
      });
    }
    imgLoad('myLittleVader.jpg').then(function(response) {
      var myImage = new Image();
      var imageURL = window.URL.createObjectURL(response); // resolve action
      myImage.src = imageURL;
    }, function(Error) {
      console.log(Error); // reject action
    });

    // Promise prototype methods

    // p.then(onFulfilled[, onRejected]);
    // p.then((value) => { /* fulfillment */ }, (reason) => { /* rejection */ });
    var promise1 = new Promise(function(resolve, reject) { resolve('Success!'); });
    promise1.then(function(value) { console.log(value); }); // "Success!"
    // p.catch(onRejected) - same as Promise.prototype.then(undefined, onRejected)
    // p.catch(function(reason) { /* rejection */ });
    var promise1 = new Promise(function(resolve, reject) { throw 'Oops!'; });
    promise1.catch(function(error) { console.log(error); }); // Oops!
    // p.finally(onFinally) - avoid duplicating code then() and catch() handlers
    // p.finally(function() { /* settled (fulfilled or rejected) */ });
    let isLoading = true;
    fetch(myRequest).then(function(response) {
      var contentType = response.headers.get("content-type");
      if(contentType && contentType.includes("application/json")) {
        return response.json();
      }
      throw new TypeError("Oops, we haven't got JSON!");
    })
    .then(function(json) { /* process your JSON further */ })
    .catch(function(error) { console.log(error); })
    .finally(function() { isLoading = false; });

    // chain
    doSomething().then(function(result) {
      return doSomethingElse(result);
    })
    .then(function(newResult) {
      return doThirdThing(newResult);
    })
    .then(function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    })
    .catch(failureCallback);

    // with arrow functions
    doSomething()
    .then(result => doSomethingElse(result))
    .then(newResult => doThirdThing(newResult))
    .then(finalResult => {
      console.log(`Got the final result: ${finalResult}`);
    })
    .catch(failureCallback);

    // chain after fail
    new Promise((resolve, reject) => {
      console.log('Initial');
      resolve();
    })
    .then(() => {
      throw new Error('Something failed');
      console.log('Do this'); // will be skipped because of Error
    })
    .catch(() => {
      console.log('Do that');
    })
    .then(() => {
      console.log('Do this, no matter what happened before');
    });
    // will output: Initial . Do that  . Do this, no matter what happened before
  

METHODS


    // --- Promise.all(iterable)
    // returns single promise when ALL promises from iterable are resolved OR when no promises
    // rejects on any first rejection (independent of sequence)
    var promise1 = Promise.resolve(3);
    var promise2 = 42;
    var promise3 = new Promise(function(resolve, reject) { setTimeout(resolve, 3000, 'foo'); });
    Promise.all([promise1,promise2,promise3]).then(function(values){console.log(values);});
    // [3, 42, "foo"] - after 3 seconds (because of promise3)

    // --- Promise.race(iterable) - returns first resolved/rejected promise
    // empty iterable is always in pending-state
    var promise1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, 'one'); });
    var promise2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'two'); });
    Promise.race([promise1, promise2])
    .then(function(value) { console.log(value); }); // "two" - promise2 is faster

    // --- Promise.allSettled() (ES2020) - returns a promise that resolves after all either fulfilled or rejected,
    // with an array of objects that each describes the outcome of each promise
    // for multiple asynchronous tasks that are not dependent on one another to complete successfully
    // or for result of each promise
    // Promise.all() more appropriate for dependent on each other tasks OR immediately reject upon any
    const promise1 = Promise.resolve(3);
    const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
    const promises = [promise1, promise2];
    Promise.allSettled(promises).
      then((results) => results.forEach((result) => console.log(result.status)));
    // expected output: "fulfilled" "rejected"
    Promise.allSettled([
      Promise.resolve(33),
      new Promise(resolve => setTimeout(() => resolve(66), 0)),
      99,
      Promise.reject(new Error('an error'))
    ])
    .then(values => console.log(values));
    // [
    //   {status: "fulfilled", value: 33},
    //   {status: "fulfilled", value: 66},
    //   {status: "fulfilled", value: 99},
    //   {status: "rejected",  reason: Error: an error}
    // ]

    // --- Promise.any() (ES2021) - accepts an iterable of promises
    // returns a promise that is fulfilled by the first given promise to be fulfilled,
    // or rejected with an AggregateError/exception if all of the given promises are rejected
    try {
      const first = await Promise.any(promises);
      // Any of the promises was fulfilled.
    } catch (error) {
      // All of the promises were rejected.
    }
    Promise.any(promises).then(
      (first) => {
        // Any of the promises was fulfilled.
      },
      (error) => {
        // All of the promises were rejected.
      }
    );
    Promise.any([
      fetch('https://v8.dev/').then(() => 'home'),
      fetch('https://v8.dev/blog').then(() => 'blog'),
      fetch('https://v8.dev/docs').then(() => 'docs')
    ]).then((first) => {
      // Any of the promises was fulfilled.
      console.log(first);
      // 'home'
    }).catch((error) => {
      // All of the promises were rejected.
      console.log(error);
    });
  
name description
Promise.allSettled does not short-circuit
Promise.all short-circuits when an input value is rejected
Promise.race short-circuits when an input value is settled
Promise.any short-circuits when an input value is fulfilled

async/await (ES2017)


    async function [name]([param1[, param2[, ..., paramN]]]) { /* statements */ }

    async function logInOrder(urls) {
      // fetch all the URLs in parallel
      const textPromises = urls.map(async url => {
        const response = await fetch(url);
        return response.text();
      });
      // log them in sequence, all works in parallel
      for (const textPromise of textPromises) {
        console.log(await textPromise);
      }
    }
    // VS unparaller
    async function logInOrder(urls) {
      for (const url of urls) {
        const response = await fetch(url);
        console.log(await response.text());
      }
    }

    async function getResponseSize(url) {
      const response = await fetch(url);
      const reader = response.body.getReader();
      let result = await reader.read();
      let total = 0;
      while (!result.done) {
        const value = result.value;
        total += value.length;
        console.log('Received chunk', value);
        // get the next result
        result = await reader.read();
      }
      return total;
    }
    // IS THE SAME AS
    function getResponseSize(url) {
      return fetch(url).then(response => {
        const reader = response.body.getReader();
        let total = 0;
        return reader.read().then(function processResult(result) {
          if (result.done) return total;
          const value = result.value;
          total += value.length;
          console.log('Received chunk', value);
          return reader.read().then(processResult);
        })
      });
    }

    function resolveAfter2Seconds(x) {
      return new Promise(resolve => {
        setTimeout(() => { resolve(x); }, 2000);
      });
    };

    async function asyncCall() {
      console.log('calling');
      var result = await resolveAfter2Seconds('resolved');
      console.log(result);
    }
    asyncCall(); // 'calling' , then after 2 seconds: 'resolved'

    // as a variable
    var add = async function(x) {
      var a = await resolveAfter2Seconds(20);
      var b = await resolveAfter2Seconds(30);
      return x + a + b;
    };
    add(10).then(v => {console.log(v);}); // prints 60 after 4 seconds.

    // as an IIFE (immediately-invoked function)
    (async function(x) {
      var p_a = resolveAfter2Seconds(20);
      var p_b = resolveAfter2Seconds(30);
      return x + await p_a + await p_b;
    })(10).then(v => {
      console.log(v);  // prints 60 after 2 seconds.
    });
  

Sequent, Concurrent, Parallel


    var resolveAfter2Seconds = function() {
      console.log("starting slow promise");
      return new Promise(resolve => {
        setTimeout(function() {
          resolve(20);
          console.log("slow promise is done");
        }, 2000);
      });
    };
    var resolveAfter1Second = function() {
      console.log("starting fast promise");
      return new Promise(resolve => {
        setTimeout(function() {
          resolve(10);
          console.log("fast promise is done");
        }, 1000);
      });
    };

    // in sequentialStart, concurrentStart, concurrentStartWithPromiseAll
    // resolve() of resolveAfter2Seconds and resolveAfter1Second arrives at the end of ALL executions

    var sequentialStart = async function() {
      const slow = await resolveAfter2Seconds();
      const fast = await resolveAfter1Second();
      // second timer is not created until the first has already fired
      console.log(slow);
      console.log(fast);
    }
    sequentialStart(); // takes 2+1 seconds in total: execute slow then fast

    var concurrentStart = async function() {
      const slow = resolveAfter2Seconds(); // starts timer immediately
      const fast = resolveAfter1Second();
      // timers are running concurrently, but await calls in series
      console.log(await slow);
      console.log(await fast); // waits for slow to finish, even though fast is already done!
    }
    concurrentStart(); // takes 2 seconds in total: start both then, fast will finish first, then slow

    var concurrentStartWithPromiseAll = function() {
      Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(([slow, fast]) => {
        console.log(slow);
        console.log(fast);
      });
    }
    concurrentStartWithPromiseAll(); // same as previous

    // in parallelWithPromiseThen, resolve() of resolveAfter2Seconds and resolveAfter1Second
    // will arrive at the end of EACH executions, by not waiting other to finish
    var parallelWithPromiseThen = function() {
      resolveAfter2Seconds().then((message)=>console.log(message));
      // in this case could be simply written as console.log(resolveAfter2Seconds());
      resolveAfter1Second().then((message)=>console.log(message));
    }
    parallelWithPromiseThen();

    // promise chain VS async function
    function getProcessedData(url) {
      return downloadData(url)              // returns a promise
        .catch(e => {
          return downloadFallbackData(url)  // returns a promise
        }).then(v => {
          return processDataInWorker(v);    // returns a promise
        });
    }
    // IS THE SAME AS
    async function getProcessedData(url) {
      let v;
      try {
        v = await downloadData(url);
      } catch(e) {
        v = await downloadFallbackData(url);
      }
      // v - is return value of an async function (wrapped in Promise.resolve)
      // no need for await statement on the return statement
      return processDataInWorker(v);
    }
  

Iterator/Generator (ES2015)


    // ITERATOR
    function makeRangeIterator(start = 0, end = Infinity, step = 1) {
      var nextIndex = start, n = 0, returned = false;
      var rangeIterator = {
        next: function() {
          var result;
          if (nextIndex < end) {
            result = { value: nextIndex, done: false };
            nextIndex += step;
            n += 1;
          } else if (!returned) {
            result = { value: n, done: true };
            returned = true;
          } else {
            result = { done: true }; // final value already returned
          }
          return result;
        }
      };
      return rangeIterator;
    }

    // ITERABLE
    var myIterable = {
      *[Symbol.iterator]() { yield 1; yield 2; yield 3; }
    }
    for (let value of myIterable) { console.log(value); } // 1 , 2 , 3
    //  or
    [...myIterable]; // [1, 2, 3]

    // syntaxes expecting iterables
    for (let value of ['a', 'b', 'c']) { console.log(value); } // a , b , c
    [...'abc']; // ["a", "b", "c"]
    function* gen() { yield* ['a', 'b', 'c']; }
    gen().next(); // { value: "a", done: false }
    [a, b, c] = new Set(['a', 'b', 'c']); a; // "a"

    // ASYNC
    let range = {
      from: 1,
      to: 5,
      [Symbol.asyncIterator]() { // (1)
        return {
          current: this.from,
          last: this.to,
          async next() { // (2)
            // note: we can use "await" inside the async next:
            await new Promise(resolve => setTimeout(resolve, 1000)); // (3)
            if (this.current <= this.last) {
              return { done: false, value: this.current++ };
            } else {
              return { done: true };
            }
          }
        };
      }
    };
    let range = {
      from: 1,
      to: 5,
      // this line is same as [Symbol.asyncIterator]: async function*() {
      async *[Symbol.asyncIterator]() {
        for(let value = this.from; value <= this.to; value++) {
          // make a pause between values, wait for something
          await new Promise(resolve => setTimeout(resolve, 1000));
          yield value;
        }
      }
    };
    (async () => {
      for await (let value of range) { // (4)
        alert(value); // 1,2,3,4,5
      }
    })()
  

    // GENERATOR
    // function* [name]([param1[, param2[, ..., paramN]]]) { /*statements*/ }
    // new GeneratorFunction ([arg1[, arg2[, ...argN]],] functionBody)
    function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
      let n = 0;
      for (let i = start; i < end; i += step) { n += 1; yield i; }
      return n;
    }
    function* idMaker() {
        var index = 0;
        while(true) { yield index++; }
    }
    var idGen = idMaker();
    // USAGE
    var it = makeRangeIterator(1, 10, 2);
    var result = it.next();
    while (!result.done) {
      console.log(result.value); // 1 3 5 7 9
      result = it.next();
    }
    console.log("Iterated over sequence of size: ", result.value); // 5

    console.log(idGen.next().value); // 0
    console.log(idGen.next().value); // 1
    console.log(idGen.next().value); // 2

    // restart generator with next()
    function* fibonacci() {
      var fn1 = 0, fn2 = 1;
      while (true) {
        var current = fn1;
        fn1 = fn2;
        fn2 = current + fn1;
        var reset = yield current;
        if (reset) { fn1 = 0; fn2 = 1; }
      }
    }
    var sequence = fibonacci();
    console.log(sequence.next().value);     // 0
    console.log(sequence.next().value);     // 1
    console.log(sequence.next().value);     // 1
    console.log(sequence.next().value);     // 2
    console.log(sequence.next().value);     // 3
    console.log(sequence.next().value);     // 5
    console.log(sequence.next(true).value); // 0
    console.log(sequence.next().value);     // 1 ...

    // yield*
    function* g1() { yield 2; yield 3; yield 4; }
    function* g2() { yield 1; yield* g1(); yield 5; }
    function* g3() {
      yield* g2();
      yield* [1, 2];
      yield* '34';
      yield* Array.from(arguments);
    }
    var iterator = g3(5, 6);
    console.log(iterator.next()); // {value: 1, done: false} - g2
    console.log(iterator.next()); // {value: 2, done: false} - g1
    console.log(iterator.next()); // {value: 3, done: false} - g1
    console.log(iterator.next()); // {value: 4, done: false} - g1
    console.log(iterator.next()); // {value: 5, done: false} - g2
    console.log(iterator.next()); // {value: 1, done: false}
    console.log(iterator.next()); // {value: 2, done: false}
    console.log(iterator.next()); // {value: "3", done: false} - part of string
    console.log(iterator.next()); // {value: "4", done: false} - part of string
    console.log(iterator.next()); // {value: 5, done: false}
    console.log(iterator.next()); // {value: 6, done: false}
    console.log(iterator.next()); // {value: undefined, done: true}

    // ASYNC
    async function* generateSequence(start, end) {
      for (let i = start; i <= end; i++) {
        // Wow, can use await!
        await new Promise(resolve => setTimeout(resolve, 1000));
        yield i;
      }
    }
    (async () => {
      let generator = generateSequence(1, 5);
      for await (let value of generator) {
        alert(value); // 1, then 2, then 3, then 4, then 5 (with delay between)
      }
      result = await generator.next(); // result = {value: ..., done: true/false}
    })();

    async function* fetchCommits(repo) {
      let url = `https://api.github.com/repos/${repo}/commits`;
      while (url) {
        const response = await fetch(url, { // (1)
          headers: {'User-Agent': 'Our script'}, // github needs any user-agent header
        });
        const body = await response.json(); // (2) response is JSON (array of commits)
        // (3) the URL of the next page is in the headers, extract it
        let nextPage = response.headers.get('Link').match(/<(.*?)>; rel="next"/);
        nextPage = nextPage?.[1];
        url = nextPage;
        for(let commit of body) { // (4) yield commits one by one, until the page ends
          yield commit;
        }
      }
    }
    (async () => {
      let count = 0;
      for await (const commit of fetchCommits('javascript-tutorial/en.javascript.info')) {
        console.log(commit.author.login);
        if (++count == 100) { // let's stop at 100 commits
          break;
        }
      }
    })();
  

Atomics (ES2017)


    const sab = new SharedArrayBuffer(1024);
    const ta = new Uint8Array(sab);
    ta[0]; // 0
    ta[0] = 5; // 5

    // --- load(typedArray, index) - returns the value at the specified index of the array

    // --- add(typedArray, index, value) - adds value to the existing value at the specified index of the array
    // returns old value at index
    Atomics.add(ta, 0, 12); // 5
    Atomics.load(ta, 0); // 17
    // --- and(typedArray, index, value) - computes a bitwise AND on the value at the specified index of the array with the provided value
    // returns old value at index
    Atomics.and(ta, 0, 1); // 17
    Atomics.load(ta, 0); // 1
    // --- compareExchange(typedArray, index, expectedValue, replacementValue)
    // stores a value at the specified index of the array, if it equals a value, returns old value
    Atomics.compareExchange(ta, 0, 5, 12); // 1
    Atomics.load(ta, 0); // 1
    // --- exchange(ypedArray, index, value)
    // stores a value at the specified index of the array, returns old value
    Atomics.exchange(ta, 0, 12); // 1
    Atomics.load(ta, 0); // 12
    // --- isLockFree(size)
    // optimization primitive that can be used to determine whether to use locks or atomic operations
    // returns true if an atomic operation on arrays of the given element size
    // will be implemented using a hardware atomic operation (as opposed to a lock), experts only
    Atomics.isLockFree(1); // true
    Atomics.isLockFree(2); // true
    Atomics.isLockFree(3); // false
    Atomics.isLockFree(4); // true
    // --- or(typedArray, index, value)
    // computes a bitwise OR on the value at the specified index of the array with the provided value
    // returns old value at index
    Atomics.or(ta, 0, 1); // 12
    Atomics.load(ta, 0);  // 13
    // --- store(typedArray, index, value) - stores a value at the specified index of the array, returns the value
    Atomics.store(ta, 0, 12); // 12
    // --- sub(typedArray, index, value) - subtracts a value at the specified index of the array
    // returns old value at index
    Atomics.sub(ta, 0, 2); // 12
    Atomics.load(ta, 0); // 10
    // --- xor(typedArray, index, value)
    // computes a bitwise XOR on the value at the specified index of the array with the provided value
    // returns old value at index
    Atomics.xor(ta, 0, 1); // 10
    Atomics.load(ta, 0); // 11

    // WAITING AND NOTIFIYING
    // --- wait() - verifies that the specified index of the array still contains a value and sleeps awaiting or times out
    // returns "ok", "not-equal", or "timed-out"
    // if waiting is not allowed in the calling agent then it throws an Error exception
    // (Most browsers will not allow wait() on the main thread)
    // --- notify() - notifies agents that are waiting on the specified index of the array
    // returns the number of agents that were notified
    const sab = new SharedArrayBuffer(1024);
    const int32 = new Int32Array(sab);
    // reading thread is sleeping and waiting on location 0 which is expected to be 0
    // as long as that is true, it will not go on
    // once the writing thread has stored a new value, it will be notified by the writing thread and return the new value (123)
    Atomics.wait(int32, 0, 0);
    console.log(int32[0]); // 123
    // writing thread stores a new value and notifies the waiting thread once it has written
    console.log(int32[0]); // 0;
    Atomics.store(int32, 0, 123);
    Atomics.notify(int32, 0, 1);
  

Modules (ES2015)


    /*
      EXPORT
      nameN - identifier to be exported (to import in another script)
    */
    export { name1, name2, …, nameN };
    export { variable1 as name1, variable2 as name2, …, nameN };
    export let name1, name2, …, nameN; // also var, const
    export let name1 = …, name2 = …, …, nameN; // also var, const
    export function FunctionName(){...}
    export class ClassName {...}

    export default expression;
    export default function (…) { … } // also class, function*
    export default function name1(…) { … } // also class, function*
    export { name1 as default, … };

    // reexport from other module
    export * from …;
    export { name1, name2, …, nameN } from …;
    export { name1 as importName1, name2 as importName2, …, nameN } from …;
    export { default } from …;

    export { myFunction }; // exports a function declared earlier
    export { cube, foo, graph };
    export const foo = Math.sqrt(2);
    export * from …; // export all except default
    export default k = 12;
    export {default} from 'mod'; // export default
  

    /*
      IMPORT
      local_name - name of the module object, kind of namespace for referring
      export - name of the exports to be imported
      alias - names that will refer to the named imports
    */
    import defaultExport from "module-name";
    import * as local_name from "module-name";
    import { export } from "module-name";
    import { export as alias } from "module-name";
    import { export1 , export2 } from "module-name";
    import { export1 , export2 as alias2 , [...] } from "module-name";
    import defaultExport, { export [ , [...] ] } from "module-name";
    import defaultExport, * as local_name from "module-name";
    import "./module-name.js";
    var promise = import(module-name);

    import * as myModule from './js/exported'; // entire, with namespace alias
    import {foo, bar} from '/modules/my-module.js'; // multiple
    import {myExport} from '/modules/my-module.js'; // single

    // aliases
    import {longExportName as shortName}
    from '/modules/my-module.js';

    import {
      reallyReallyLongModuleExportName as shortName,
      anotherLongModuleName as short
    } from '/modules/my-module.js';

    // import default export
    import myDefault from '/modules/my-module.js';

    // import default export and entire module as alias
    import myDefault, * as myModule from '/modules/my-module.js';

    // import default export and specific, named imports
    import myDefault, {foo, bar} from '/modules/my-module.js';

    // import for side effects only
    // run the module global code, but doesnt import any values
    import '/modules/my-module.js';

    // dynamic import
    import('/modules/my-module.js')
    .then((module) => { /* do something with the module */ });
    // OR
    let module = await import('/modules/my-module.js');
  

EXAMPLES


    /* ----- file.js ----- */
    function getJSON(url, callback) {
      let xhr = new XMLHttpRequest();
      xhr.onload = function () { callback(this.responseText) };
      xhr.open('GET', url, true);
      xhr.send();
    }
    export function getUsefulContents(url, callback) {
      getJSON(url, data => callback(JSON.parse(data)));
    }

    /* ----- main.js ----- */
    import { getUsefulContents } from '/modules/file.js';
    getUsefulContents('http://www.example.com',
        data => { doSomethingUseful(data); });

    /* ----- dynamic import ----- */
    const main = document.querySelector("main");
    for (const link of document.querySelectorAll("nav > a")) {
      link.addEventListener("click", e => {
        e.preventDefault();
        import('/modules/my-module.js')
        .then(module => { module.loadPageInto(main); })
        .catch(err => { main.textContent = err.message; });
      });
    }

    // classes/function declarations can be authored directly as default exports:
    // class ->
    export default class ZipCodeValidator {
      static numberRegexp = /^[0-9]+$/;
      isAcceptable(s: string) {
        return s.length === 5 && ZipCodeValidator.numberRegexp.test(s);
      }
    }
    // ->
    import validator from "./ZipCodeValidator";
    let myValidator = new validator();
    // function ->
    const numberRegexp = /^[0-9]+$/;
    export default function (s: string) {
      return s.length === 5 && numberRegexp.test(s);
    }
    // ->
    import validate from "./StaticZipCodeValidator";
    let strings = ["Hello", "98052", "101"];
    // Use function validate
    strings.forEach(s => {
      console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);
    });
  

EXPORT REDIRECT


    /* ----- js/exported.js ----- */
    export default function cube(x) {
      return x * x * x;
    }
    const foo = Math.PI + Math.SQRT2;
    var graph = {
      options:{
        color:'white',
        thickness:'2px'
      },
      draw: function(){
        console.log('From graph draw function');
      }
    }
    export { cube, foo, graph };
    export function sum(a, b) { return a + b; }

    /* ----- js/exported-redirect.js ----- */
    export {default} from './exported';
    export * from './exported';

    /* ----- on this page ----- */
    <script type="module" /*src="..."*/ >
      import cube from './js/exported-redirect';
      console.log(cube(3));

      import { foo, graph } from './js/exported-redirect';
      graph.options = {
        color:'blue',
        thickness:'3px'
      };
      graph.draw();
      console.log(foo);

      import { sum } from './js/exported-redirect';
      console.log(sum(1, 2));
    </script>
  

Micro/MacroTask

Reserved words

abstract arguments await* boolean
break byte case catch
char class* const continue
debugger default delete do
double else enum* eval
export* extends* false final
finally float for function
goto if implements import*
in instanceof int interface
let* long native new
null package private protected
public return short static
super* switch synchronized this
throw throws transient true
try typeof var void
volatile while with yield
Array Date eval function
hasOwnProperty Infinity isFinite isNaN
isPrototypeOf length Math NaN
name Number Object prototype
String toString undefined valueOf
alert all anchor anchors
area assign blur button
checkbox clearInterval clearTimeout clientInformation
close closed confirm constructor
crypto decodeURI decodeURIComponent defaultStatus
document element elements embed
embeds encodeURI encodeURIComponent escape
event fileUpload focus form
forms frame innerHeight innerWidth
layer layers link location
mimeTypes navigate navigator frames
frameRate hidden history image
images offscreenBuffering open opener
option outerHeight outerWidth packages
pageXOffset pageYOffset parent parseFloat
parseInt password pkcs11 plugin
prompt propertyIsEnum radio reset
screenX screenY scroll secure
select self setInterval setTimeout
status submit taint text
textarea top unescape untaint
window
onblur onclick onerror onfocus
onkeydown onkeypress onkeyup onmouseover
onload onmouseup onmousedown onsubmit

Debugging (console, breakpoints)

Optimization

Tricks


    // --- --- borrowing methods
    // --- pseudoclassical pattern
    //
    var extendObj = function(childObj, parentObj) {
      // JS passes objects by reference, not by value,
      // all children of Human inherit changes occurred on other children prototypes
      var tmpObj = function () {}
      tmpObj.prototype = parentObj.prototype;
      childObj.prototype = new tmpObj();
      childObj.prototype.constructor = childObj;
    };
    // base human object
    var Human = function () {};
    // inhertiable attributes / methods
    Human.prototype = {
      name: '',
      gender: '',
      planetOfBirth: 'Earth',
      sayGender: function () {
        alert(this.name + ' says my gender is ' + this.gender);
      },
      sayPlanet: function () {
        alert(this.name + ' was born on ' + this.planetOfBirth);
      }
    };
    // male
    var Male = function (name) {
      this.gender = 'Male';
      this.name = 'David';
    };
    // inherits human
    extendObj(Male, Human);
    // female
    var Female = function (name) {
      this.name = name;
      this.gender = 'Female';
    };
    // inherits human
    extendObj(Female, Human);
    // new instances
    var david = new Male('David');
    var jane = new Female('Jane');
    david.sayGender(); // David says my gender is Male
    jane.sayGender(); // Jane says my gender is Female
    Male.prototype.planetOfBirth = 'Mars';
    david.sayPlanet(); // David was born on Mars
    jane.sayPlanet(); // Jane was born on Earth
    // --- functional pattern
    // following has a downside for performance because each object is unique,
    // meaning each function call creates a new object
    // benefits to this approach, as the closures of each function
    // allow for good use of public and private methods/attributes
    var human = function(name) {
      var that = {};
      that.name = name || '';
      that.gender = '';
      that.planetOfBirth = 'Earth';
      that.sayGender = function () {
        alert(that.name + ' says my gender is ' + that.gender);
      };
      that.sayPlanet = function () {
        alert(that.name + ' was born on ' + that.planetOfBirth);
      };
      return that;
    }
    var male = function (name) {
      var that = human(name);
      that.gender = 'Male';
      return that;
    }
    var female = function (name) {
      var that = human(name);
      that.gender = 'Female';
      return that;
    }
    var david = male('David');
    var jane = female('Jane');
    david.sayGender(); // David says my gender is Male
    jane.sayGender(); // Jane says my gender is Female
    david.planetOfBirth = 'Mars';
    david.sayPlanet(); // David was born on Mars
    jane.sayPlanet(); // Jane was born on Earth
    // fairly easy to provide encapsulation
    // _privateObj can not be modified from outside of the object,
    // unless exposed by a public method like increaseWheels()
    // similarly, private values can also only be read when exposed by a public method,
    // such as motorbike totalNumWheels() function
    var vehicle = function(attrs) {
      var _privateObj = { hasEngine: true },
      that = {};
      that.name = attrs.name || null;
      that.engineSize = attrs.engineSize || null;
      that.hasEngine = function () {
        alert('This ' + that.name + ' has an engine: ' + _privateObj.hasEngine);
      };
      return that;
    }
    var motorbike = function () {
      // private
      var _privateObj = { numWheels: 2 },
      // inherit
      that = vehicle({
        name: 'Motorbike',
        engineSize: 'Small'
      });
      // public
      that.totalNumWheels = function () {
        alert('This Motobike has ' + _privateObj.numWheels + ' wheels');
      };
      that.increaseWheels = function () {
        _privateObj.numWheels++;
      };
      return that;
    };
    var boat = function () {
      // inherit
      that = vehicle({
        name: 'Boat',
        engineSize: 'Large'
      });
      return that;
    };
    myBoat = boat();
    myBoat.hasEngine(); // This Boat has an engine: true
    alert(myBoat.engineSize); // Large
    myMotorbike = motorbike();
    myMotorbike.hasEngine(); // This Motorbike has an engine: true
    myMotorbike.increaseWheels();
    myMotorbike.totalNumWheels(); // This Motorbike has 3 wheels
    alert(myMotorbike.engineSize); // Small
    myMotorbike2 = motorbike();
    myMotorbike2.totalNumWheels(); // This Motorbike has 2 wheels
    myMotorbike._privateObj.numWheels = 0; // undefined
    myBoat.totalNumWheels(); // undefined
    // --- prototypal pattern
    var male = Object.create(human);
    // augment the Object with a create method should it not exist already,
    // which will have the same behavior as that of ES5
    (function () {
      'use strict';
      // Helper functions for older browsers
      if (!Object.hasOwnProperty('create')) {
        Object.create = function (parentObj) {
          function tmpObj() {}
          tmpObj.prototype = parentObj;
          return new tmpObj();
        };
      }
      if (!Object.hasOwnProperty('defineProperties')) {
        Object.defineProperties = function (obj, props) {
          for (var prop in props) {
            Object.defineProperty(obj, prop, props[prop]);
          }
        };
      }
      var human = {
        name: '',
        gender: '',
        planetOfBirth: 'Earth',
        sayGender: function () {
          alert(this.name + ' says my gender is ' + this.gender);
        },
        sayPlanet: function () {
          alert(this.name + ' was born on ' + this.planetOfBirth);
        }
      };
      var male = Object.create(human, {
        gender: {value: 'Male'}
      });
      var female = Object.create(human, {
        gender: {value: 'Female'}
      });
      var david = Object.create(male, {
        name: {value: 'David'},
        planetOfBirth: {value: 'Mars'}
      });
      var jane = Object.create(female, {
        name: {value: 'Jane'}
      });
      david.sayGender(); // David says my gender is Male
      david.sayPlanet(); // David was born on Mars
      jane.sayGender(); // Jane says my gender is Female
      jane.sayPlanet(); // Jane was born on Earth
    })();

    // --- --- borrowing methods
    function myFunc() {
      // error, arguments is an array like object, not a real array
      arguments.sort();
      // "borrow" the Array method slice from its prototype, which takes an array like object (key:value)
      // and returns a real array
      var args = Array.prototype.slice.call(arguments);
      // args is now a real Array, so can use the sort() method from Array
      args.sort();
    }
    myFunc('bananas', 'cherries', 'apples');

    // takes a string "abc" and produces "a|b|c
    Array.prototype.join.call('abc', '|');
    // takes a string and removes all non vowels
    Array.prototype.filter.call('abcdefghijk', function(val) {
      return ['a', 'e', 'i', 'o', 'u'].indexOf(val) !== -1;
    }).join('');

    [].slice.call(arguments);
    [].join.call('abc', '|');
    ''.toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

    var slice = [].slice;
    slice.call(arguments);
    var join = [].join;
    join.call('abc', '|');
    var toUpperCase = ''.toUpperCase;
    toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

    var slice = Function.prototype.call.bind(Array.prototype.slice);
    slice(arguments);
    var join = Function.prototype.call.bind(Array.prototype.join);
    join('abc', '|');
    var toUpperCase = Function.prototype.call.bind(String.prototype.toUpperCase);
    toUpperCase(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

    // --- methods from custom objects
    var scoreCalculator = {
      getSum: function(results) {
        var score = 0;
        for (var i = 0, len = results.length; i < len; i++) {
            score = score + results[i];
        }
        return score;
      },
      getScore: function() {
        return scoreCalculator.getSum(this.results) / this.handicap;
      }
    };
    var player1 = {
      results: [69, 50, 76],
      handicap: 8
    };
    var player2 = {
      results: [23, 4, 58],
      handicap: 5
    };
    var score = Function.prototype.call.bind(scoreCalculator.getScore);
    // Score: 24.375
    console.log('Score: ' + score(player1));
    // Score: 17
    console.log('Score: ' + score(player2));
  

Back to Main Page