Generators for idle-until-urgent

Using a generator function’s yield we can segment a long running process into small chunks that fit the Idle Until Urgent pattern.

const promise = new IdlePromise(function* (resolve, reject) {
    chunkA()
    yield
    chunkB()
    yield
    chunkC()
    resolve()
})

Read more

Proxy & Reflect

You can customize all the ways objects are manipulated with Proxy, and still use the built in object prototype methods with Reflect.

const proxy = new Proxy(object, Reflect)

Read more

Proxy use cases

Proxy allows you to intercept all object prototype methods.

new Proxy(object, {
    get: (obj, key) => { return 42 }
}) // the answer to everything is 42

Read more

Conditional object attribute

Just a simple way to conditionnaly add a key-value pair at object declaration.

const obj = {
    ...(flag && {key: value})
}

Read more

So many closures

When only a small portion of your function needs to change, try to encapsulate it one level of abstraction above.

const getNavTo = index => () => {
    navigateTo(index)
}
document.querySelectorAll('.tab').forEach(($el, index) => {
    $el.addEventListener('click', getNavTo(index))
})

Read more

CSS “contain” property

The contain CSS property allows you to define an element as a style boundary in order to optimize the browser’s paints, layouts, composite, and style contexts calculations.

.el {
    contain: strict;
}

Read more

#id is in window

DOM node IDs are directly available in the window object.

<div id='foo'></div>
console.log(window.foo) // HTMLElement

Though, you shouldn’t access the DOM that way.

Read more

Synthetic events

We can create our own event types, listen to and emmit them from anywhere, and implement event driven behaviors.

$el.addEventListener('foo', () => { 
    console.log('received foo event') 
})
$el.dispatchEvent(new CustomEvent('foo'))
// 'received foo event'

Read more

Getters & setters

JavaScript allows you to intercept when an object property is accessed or assigned to.

const foo = {
    bar: 42,
    get bar() { return this.bar + 1 }
}
console.log(foo.bar) // 43

Read more

Thenables & trigger promises

Any object containing a then() property — also called a thenable — can be turned into a promise.

const foo = {
    then: fn => fn(42)
}
Promise.resolve(foo).then(console.log) // 42

Read more

Logical operators coerce internally

Logical operators || and && can return non boolean values after internal boolean operations have resolved. Type coercion is only internal.

const foo = true && 'foo' // 'foo'
const bar = false || 'bar' // 'bar'

Read more

Object assign

Object.assign() is a method that allows you to easily merge, override, clone, default object properties.

const foo = {foo: 'foo'}
Object.assign(foo, {bar: 'bar'})
console.log(foo.bar) // 'bar'

Read more

Idle until urgent

Defer calculation of costly values to idle periods, but compute immediately if it is needed before that.

let foo = {
    get value() {
        if (this._value)
            return this._value
        cancelIdleCallback(idleHandle)
        return costly()
    }
}
const idleHandle = requestIdleCallback(() => foo._value = costly())

Read more

Functions as arguments

You don’t need to declare an anonymous function to use as an argument.

// Don't
functionCallback(value => console.log(value))
// Do
functionCallback(console.log)

Read more

AddEventListener third argument

We don’t often see addEventListener() be used with a third argument, but it allows for great preformance improvements and cleaner code.

window.addEventListener('scroll', () => {}, {passive: true})
$el.addEventListener('click', () => {}, {once: true})

Read more

Lazy getter

Compute a value only when needed, but then only once.

get bar() {
    const bar = getBar()
    Object.defineProperty(this, 'bar', { value: bar })
    return bar
}

Read more