JavaScript / ECMAScript (by Brendan Eich 1995) is an ECMA standard since 1997, ECMAScript is the official name of the language.

ES version ECMA Name
ES5 - ECMAScript 2009
ES6 - ECMAScript 2015
ES7 - ECMAScript 2016
ES8 - ECMAScript 2017
ES9 - ECMAScript 2018
ES10 ECMA-262 ECMAScript 2019

Transpile via Babel

Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.

      ES6        |      ES5
-----------------+--------------------
const a = 123;   |  "use strict";
                 |  var a = 123;
-----------------+--------------------
Values: primitive / reference
debug via console API
  • console.clear(): clear console
  • console.log() / .debug() / .warn() / .error(): use %c directive to apply CSS style
console.warn("abc");
console.log("%s %d", "int", 1.555);
console.log("%s %.1f", "float", 1.555);
console.error("Error %o: ", { keyA: 'valA', keyB: 123, keyC: ["a", "b", "c"] } );
console.log('%c big ABC', 'font-size:x-large;color:#f00;')
  • console.table():
console.table({ keyA: 'valA', keyB: 123, keyC: ["a", "b", "c"] } );
  • console.dir(): prints interactive list of object properties
console.dir({ keyA: 'valA', keyB: ["a", "b", "c"] } );
  • console.group() / .groupEnd() / .groupCollapsed():
console.log("START");
console.groupCollapsed("group 1") ; console.log("1 a") ; console.log("1 b") ; console.groupEnd();
console.log("END");
  • console.count() / .countReset(): log number of times this line has been called (with the given label)
console.count("count a");
  • console.time() / .timeEnd()
const longArray = Array.from({ length: 10000000 }, (_, i) => i);

console.time("forof-loop");
for (const value of longArray) {;}
console.timeEnd("forof-loop");

console.time("for-loop");
for (let i = 0; i < longArray.length; i++) {;}
console.timeEnd("for-loop");

console.time("foreach-loop");
longArray.forEach(element => {;});
console.timeEnd("foreach-loop");
  • console.memory: heap size status

developer.mozilla.org - Console

var, let and const

Before ES6: only var was available! Since ES6 const and let: let is block scoped, no need for var anymore!

That means that a variable created with the let keyword is available inside the “block” that it was created in as well as any nested blocks. When I say “block”, I mean anything surrounded by a curly brace {} like in a for loop or an if statement.

  • var: function scoped ; undefined when accessing a variable before it's declared
  • let: block scoped ; ReferenceError when accessing a variable before it's declared
  • const: block scoped ; ReferenceError when accessing a variable before it's declared ; can't be reassigned
Arrow => functions

Arrow functions are a concise method of declaring anonymous functions in JS.

Arrow function inherit this from the scope they were defined in.

// vanilla anonymous function
someMethod(1, function () {    // has no name
   console.log('called');
});

// anonymous arrow function
someMethod(1, () => {          // has no name
   console.log('called');
});
this keyword

this points to the surrounding execution context == "on what the function was called"

const myButton = document.querySelector('some-button');

myButton.addEventListener('click', function() {
  console.log(this);  // => this refer to the element on which the event occurs
});
Visibility of variables - scope
  • global: variables defined outside of any function or block statement

  • function: var variables defined inside of a function

  • block: let / const variables defined inside an block

Closure

In JavaScript every function closes over its environment on creation

Anonymous Closures A anonymous function which executes immediately. All code that runs inside the function lives in a closure, which provides privacy and state throughout the lifetime of the application.

(function () {
	// ... all vars and functions are in this scope only
	// still maintains access to all globals
}());
var test;

function fDelay() {
   setTimeout(function () {
      alert('test=' + test);
   }, 2222);
}

test = 'abc';
fDelay();
test = 'xyz';

// => alert: test=xyz
// because the value is looked up when needed and not when the closure is created
Callback, promises, async/await

JavaScript is single-threaded, that means only capable of doing one thing at the same time -> asynchronous tasks are handled by it's environment (web browser, NodeJS runtime, ...)

The biggest advantage of Promises over callbacks is readability and chainability.

An async function is 'just' a fancy promise wrapper, which means, the async/await code and the Promise code, are functionally equivalent.

setTimeout(callFunction, 5000);   // callback function handed over to the web browser


      Promises                 |      pure callback
-------------------------------+------------------------------------
fetch('data.com/abc')          |  fetch('data.com/abc')
   .then(response => {         |     response => {
      return response.json();  |        response.json(data => {
   })                          |           console.log(data);
   .then(data => {             |           // other nested callbacks
      console.log(data);       |        });
   })                          |      },
   .catch(e => {               |      e => {
      console.error(e);        |         console.error(e);
   });                         |      }
                               |   ); 
-------------------------------+------------------------------------

async function makeHttpRequest(url) { ... }
try {
   const data = await makeHttpRequest('data.com/abc');
   console.log(data);
} catch (e) {
   console.error(e);
}
Iterating DOM elements
  • for loop: supported in all browsers
const allimg = document.querySelectorAll("img");
const allimgLen = allimg.length;
for (var i = 0; i < allimgLen; i++) {
   console.log('image: ', allimg[i]);
}
  • forEach loop: supported in modern browsers, but not in IE11 and below
const allimg = document.querySelectorAll("img");
allimg.forEach(actimg => {
   console.log('image: ', actimg);
});
  • for-of loop: in modern browsers, but not in IE11 and below
const allimg = document.querySelectorAll("img");
for (const actimg of allimg) {
   console.log('image: ', actimg);
}
  • for-of {values()|entries()|keys()} loop: iterators are ES2015 specific
const allimg = document.querySelectorAll("img");
for (const actimg of allimg.values()) {
   console.log('image: ', actimg);
};
Iterating objects
  • for…in loop => fastest version
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
     console.log(key + " -> " + obj[key]);     
  }
}
  • Object.keys => slower than for…in
Object.keys(obj).forEach(function (key) {
   console.log(key + " -> " + obj[key]);
});
Object.keys(obj).forEach(key => {
   console.log(key + " -> " +   obj[key]);     
});
  • Object.entries => slowest
Object.entries(obj).forEach(entry => {
   console.log(entry[0]+ " -> " + entry[1]);
});
  • Object example
var obj= { 
   keyA: 'valueA',  
   keyB: 'valueB',
   keyC: 123,
   fPrintData: function() {
      for (const key in obj) {
         if (obj.hasOwnProperty(key)) {
            if ((typeof obj[key] === 'string') || (typeof obj[key] === 'number')) {
               console.log(key + " -> " +  obj[key]);     
            }
         }
      }
   }
};
// ---
var keyName1="myKey1";
var obj= { 
   [keyName1]: 'valueA',  
   keyB: 'valueB',
   keyC: 123,
   keyD: ["a", "b", "c"]
};

console.table(obj);
console.log(JSON.stringify(obj,null,2));
console.log(obj);
Float Precision
var a=-0.34;
var b=1.20;

x=(a+b);
alert(x);
alert(x.toPrecision(10));
alert((x.toPrecision(10)).replace(/0*$/, ''));
Load image and set background of element
var aElem, elemStyle, imgSrc, image;

aElem = document.getElementById("someElementId");
elemStyle = elem.style;
imgSrc = "someImageWithPath.jpeg";
image = new Image();
image.onload = function () {
   setTimeout(function () {
      elemStyle.backgroundImage = "url(" + imgSrc + ")";
      elemStyle.backgroundPosition = "0 0";
      image = null;
   }, 111);
};
image.src = imgSrc;
Event delegation on non-bubbling events

events like focus, blur, load, unload, change, reset, scroll,... need third argument of addEventListener "useCapture" to capture events that happen in the parent. Following example does not work without true at the end!

document.addEventListener('focus', function (event) {
   console.log('something came into focus: ' + event.target);
}, true);

JavaScript events

Vanilla JavaScript version of "run on DOM ready"
function fVanillaJsDomReady(fn) {
   if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
      fn();
   } else {
      document.addEventListener("DOMContentLoaded", fn);
   }
}

fVanillaJsDomReady(function () { 
   console.log("DOM ready ...");
}
Testing existence of property

// BAD: This will cause an error in code when foo is undefined

if (foo) {  
   doSomething();  
}  

// GOOD: This doesn't cause any errors. However, even when
// foo is set to NULL or false, the condition validates as true

if (typeof foo != "undefined") {  
   doSomething();  
} 

// BETTER: This doesn't cause any errors and in addition
// values NULL or false won't validate as true

if (window.foo) {  
   doSomething();  
}  
function: object destructuring with default parameter
function fDoSomething({pVal1, pVal2, pTime = 'today'}) {
    return `${pVal1} ${pVal2} -> time=${pTime}?`;
}
fDoSomething({
	pVal1: 'aaa',
	pVal2: 'bbb'
});

JavaScript arguments


</details>


<details><summary><strong>"random" numbers</strong></summary>

```javascript

let maxVal = 99;
for (let i = 0; i < 11; i++) {
   setTimeout(() => console.log("random value " + i + ": " + (new Date() % maxVal) + "  /  " + (Math.floor(Math.random()*maxVal))), 1000)
}
events bound in all elements on page
Array.from(document.querySelectorAll('*'))
  .reduce(function(pre, dom){
    var evtObj = getEventListeners(dom)
    Object.keys(evtObj).forEach(function (evt) {
      if (typeof pre[evt] === 'undefined') {
        pre[evt] = 0
      }
      pre[evt] += evtObj[evt].length
    })
    return pre
  }, {})
Date / toLocaleString
var dm= Date.now();  // number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.
var d= new Date();
var opt = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false };
opt.timeZone = 'UTC';
opt.timeZoneName = 'short';

console.log(": milliseconds since 1.1.1970 ", dm);
console.log(": current Date()=", d);
console.log(": UTC time zone diff to local machine time=", d.getTimezoneOffset()); 
console.log(": A: ", d.toLocaleString(navigator.language || 'de-DE', opt));
console.log(": B: ", d.toString());
console.log(": C: ", d.toDateString());
console.log(": D: ", d.toGMTString());
console.log(": E: ", d.toLocaleDateString());
console.log(": F: ", d.toISOString());
console.log(": G: ", d.toTimeString());
format numbers (currency)
var number = 123456.78987654321;
console.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR', maximumFractionDigits: 4 }));
Template literals enclosed by the backtick ` (grave accent) character instead of double or single quotes.
let a = 10;
let b = 20;
console.log(`a=${a} b=${b} =>
SUM=${a + b}`);

//---

console.log(String.raw`Hi\n${2+3}!`);
External documentation



image


Markdown test (click to expand)

github md guide

😄 😕 👍 👎 🌐 ⏱️ 📲 💻 ⌨️ 📘 📧 📝 ⬆️ ➡️ 🔝 🔚 ‼️ ✅ 🔟 🔴 🔶 ✔️

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

bold italic strikethrough Color Syntax

block quote

block quote (2 depth)

block quote (3 depth)

  • list
    • list indented
  1. ordered
  2. list
    1. ordered list
    2. indented
  • task
  • list completed

inline code

code block
console.log("fenced code block");
**HTML block**
table head
table body