Javascript

Grunt, Gulp, CoffeeScript, IIFE, overridden undefined, with, closures to create private fields, modified prototypes, variables global by default, call-site-this, automatic conversions for comparisons… Ah yes, over a decade of JS.

k__ on Hacker News

Microtasks

Runtime order

Promises run after synchronous code, but before the start of the next full event-loop cycle.

Promise.resolve(42).then(() => console.log("From promise"))
setTimeout(() => console.log("From setTimeout"), 0)
console.log("From bare console log")

Outputs:

From bare console log
From promise
From setTimeout

This isn’t a race condition, this behavior is defined in the ECMAScript spec.

Finish running all pending promises before continuing

This function returns a promise that will only resolve at the beginning of the next event-loop cycle, after all code that depends on resolved promises has run.

This is mostly useful in unit testing when you’ve mocked an interface to return Promise.resolve(some_result) and you want to assert what happens next.

// Finish running all current promises before continuing
function flushPromises() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        });
    });
}

// usage
await flushPromises();

try/finally blocks Curiosity

Competing returns

function f() {
  try {
    return "foo";
  } finally {
    return "bar";
  }
}

Will return "bar"

continue in a finally block

This will act as a bizzare infinite loop. The continue in the finally block will “win” over the return.

function f() {
  while (true) {
    try {
      return "foo";
    } finally {
      continue;
    }
  }
}
f();

Adding a let variable can be a breaking change for code above it Curiosity

With no declaration:

console.log(typeof foo); // undefined

With a let declaration:

console.log(typeof foo); // ReferenceError: can't access lexical declaration 'foo' before initialization
let foo = 50;