Web development is difficult, only then it is fun to do. You just have to set your standards. If it were to be easy, would anyone do it?
Olawale Daniel
(and vice-versa)
(and vice-versa)
const sequence = [1, 2, 3]; // will never change
sequence.group((n) => n%2 ? 'even' : 'odd'); // => {even: [2], odd: [1, 3]}
async function* asynGen(n) {
for (let i = 0; i < n; ++i) { yield i * 2 }
}
const multiply = (n) => n * 2
await Array.fromAsync(asyncGen(2), multiply); // [2, 4]
// difference/subtraction (in A but not in B)
[A--B]
// intersection (in both A and B)
[A&&B]
// nested character classes (needed to enable the above)
[A--[0-9]]
const weakmap = new WeakMap();
const key = Symbol('itsKey');
const value = 'Random';
weakmap.set(key, value);
console.log(weakmap.get(key)); // Random
const segmenter = new Intl.Segmenter(
'en', { granularity: 'sentence' // 'word', 'grapheme' }
);
console.log(
Array.from(
segmenter.segment(`I'm like 🫣. But you are, too! 🫵`),
s => s.segment
)
)// ['I'm like 🫣. ', ' But you are, too! ', '🫵']
let now = Temporal.Now.plainDate(); // To replace new Date();
let currentYear = now.getFullYear();
console.log(currentYear);
const wellFormedStr = "Hello, World!";
const illFormedStr = "Hello, \uD800 World!";
console.log(wellFormedStr.isWellFormed()); // true
console.log(illFormedStr.isWellFormed()); // false
console.log(wellFormedStr.toWellFormed()); // Hello, World!
console.log(illFormedStr.toWellFormed()); // Hello, � World!
function buildRSA(p, q) {
if (!Number.isInteger(p) || !Number.isInteger(q)) {
throw new Error("RSA key generation requires integer inputs.", {
cause: { code: "NonInteger", values: [p, q] },
});
}
if (!areCoprime(p, q)) {
throw new Error("RSA key generation requires two coprime integers.", {
cause: { code: "NonCoprime", values: [p, q] },
});
}
}
async function readFile(file) {
const { promise, resolve, reject } = Promise.withResolvers();
const reader = new FileReader();
reader.onload = resolve;
reader.onerror = reject;
reader.onabort = reject;
reader.readAsText(file);
return promise;
}
const sequence = [1, 2, 3]; // will never change
sequence.spliced(2, 2); // => [3]
sequence.toReversed(); // => [3, 2, 1]
sequence.toSorted(); // => [1, 2, 3]
sequence.with(2, 6); // => [1, 2, 6]
const proposal = #{
id: 1234,
title: "Record & Tuple proposal",
contents: `...`,
// tuples are primitive types so you can put them in records:
keywords: #["ecma", "tc39", "proposal", "record", "tuple"],
};
// Accessing keys like you would with objects!
console.log(proposal.title); // Record & Tuple proposal
console.log(proposal.keywords[1]); // tc39
// Spread like objects!
const proposal2 = #{
...proposal,
title: "Stage 2: Record & Tuple",
};
console.log(proposal2.title); // Stage 2: Record & Tuple
console.log(proposal2.keywords[1]); // tc39
// Object functions work on Records:
console.log(Object.keys(proposal)); // ["contents", "id", "keywords", "title"]
const measures = #[42, 12, 67, "measure error: foo happened"];
// Accessing indices like you would with arrays!
console.log(measures[0]); // 42
console.log(measures[3]); // measure error: foo happened
// Slice and spread like arrays!
const correctedMeasures = #[
...measures.slice(0, measures.length - 1),
-1
];
console.log(correctedMeasures[0]); // 42
console.log(correctedMeasures[3]); // -1
// or use the .with() shorthand for the same result:
const correctedMeasures2 = measures.with(3, -1);
console.log(correctedMeasures2[0]); // 42
console.log(correctedMeasures2[3]); // -1
// Tuples support methods similar to Arrays
console.log(correctedMeasures2.map(x => x + 1)); // #[43, 13, 68, 0]]
const double = (x) => x * 2;
const addFive = (x) => x + 5;
// Before: const result = addFive(double(10));
const result = 10 |> double |> addFive; // 25
const observable = new Observable((subscriber) => {
let i = 0;
setInterval(() => {
if (i >= 10) subscriber.complete();
else subscriber.next(i++);
}, 2000);
});
observable.subscribe({
next: console.log, // Print each value the Observable produces
complete: console.info, // optional
error: console.error, // optional
});
// An observable that synchronously emits unlimited data during subscription.
let observable = new Observable((subscriber) => {
let i = 0;
while (true) {
subscriber.next(i++);
}
});
let controller = new AbortController();
observable.subscribe({
next: (data) => {
if (data > 100) controller.abort();
}}, {signal: controller.signal},
});
// Filtering and mapping:
element
.on('click')
.filter((e) => e.target.matches('.foo'))
.map((e) => ({ x: e.clientX, y: e.clientY }))
.subscribe({ next: handleClickAtPoint });
const watcher = new CloseWatcher();
watcher.addEventListener("cancel", () => {
console.log("CloseWatcher cancel event");
});
watcher.addEventListener("close", () => {
document.querySelector("#sidebar").classList.remove("open");
});
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
audio.pause();
} else {
audio.play();
}
});
Simple message bus that allows pub/sub semantics between windows/tabs, iframes, web workers, and service workers on the same origin
It doesn't replace the MessageChanel api (for web workers) or window.postMessage() (for windows)
// Connect to the channel named "my_bus".
const channel = new BroadcastChannel('my_bus');
// Send a message on "my_bus".
channel.postMessage('This is a test message.');
channel.postMessage(new Blob(['foo', 'bar'], {type: 'plain/text'}));
// Strings, Objects, Arrays, Blobs, ArrayBuffer, Map
// Listen for messages on "my_bus".
channel.onmessage = function(e) {
console.log('Received', e.data);
};
// Close the channel when you're done.
channel.close();
Ability to create multiple storage buckets, where the user agent may choose to delete each bucket independently of other buckets
const draftsBucket = await navigator.storageBuckets.open(
"drafts", { durability: "strict", persisted: true });
const draftBlob = await draftsBucket.createBlob(
["Message text."], { type: "text/plain" });
const draftFile = await draftsBucket.createFile(
["Attachment data"], "attachment.txt",
{ type: "text/plain", lastModified: Date.now() });
// We could list history, add handlers on modifications, etc...
The idea: provides a simplified way to create animations between pages and to remove the scrolling position between pages
document.startViewTransition(() => updateTheDOMSomehow(data));
// if the callback is async, then we could use an async method to render the DOM
::view-transition
└─ ::view-transition-group(root)
└─ ::view-transition-image-pair(root)
├─ ::view-transition-old(root)
└─ ::view-transition-new(root);
Usually, we have only one group: root (which represents the whole page)
However we could associate an element to a specific name and set a specific transition
(e.g. if we have the same header, we could change the content in another way)
::view-transition
├─ ::view-transition-group(root)
│ └─ ::view-transition-image-pair(root)
│ ├─ ::view-transition-old(root)
│ └─ ::view-transition-new(root)
└─ ::view-transition-group(sidebar)
└─ ::view-transition-image-pair(sidebar)
├─ ::view-transition-old(sidebar)
└─ ::view-transition-new(sidebar)
.sidebar {
view-transition-name: sidebar;
}
/* Entry transition */
::view-transition-new(sidebar):only-child {
animation: 300ms cubic-bezier(0, 0, 0.2, 1) both fade-in,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
/* Exit transition */
::view-transition-old(sidebar):only-child {
animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}
@requireAuth
@requireAdmin
class SampleClass {
@trackExecution
performAction(parameter1, parameter2) {
// Method implementation goes here
}
@validateParam(0, 10)
multiply(a, b) {
return a * b;
}
}
function decoratorFactory(config) {
return function decorator(target, key, descriptor) {
// Customize the behavior of the decorator based on the 'config' argument.
// Modify the 'descriptor' or take other actions as needed.
// Descriptor is the same contract used for Object.defineProperty
};
}
Mechanism for creating isolated JavaScript environments
Useful for secure code execution and sandboxing, allowing you to run code in a controlled and isolated context
const igorsRealm = new Realm();
igorsRealm.evaluate('this'); // Throws a TypeError
igorsRealm.evaluate('new Array()'); // Throws a TypeError
igorsRealm.evaluate('Object.keys({})'); // Throws a TypeError
const doubleFunction = igorsRealm.evaluate('num => num * 2');
doubleFunction(10); // returns 20
const processNumber = igorsRealm.evaluate('(number, callback) => callback(number + 5)');
processNumber(5, (result => console.log(result))); // Logs 10 (5 + 5)
To declare a Web component, we need some imperative
this is not great for server side rendering, even to build static HTML
const host = document.getElementById('host');
const shadowRoot = host.attachShadow({mode: 'open'});
shadowRoot.innerHTML = 'Hello Shadow DOM
';
Now we have a declarative way to define a shadow dom
<menu-toggle>
<template shadowrootmode="open">
<button>
<slot></slot>
</button>
</template>
Open Menu
</menu-toggle>
It's ease hydration, avoid flash styling and could be used for server side rendering
class MenuToggle extends HTMLElement {
constructor() {
super();
// Detect whether we have SSR content already:
if (this.shadowRoot) {
// A Declarative Shadow Root exists!
// wire up event listeners, references, etc.:
const button = this.shadowRoot.firstElementChild;
button.addEventListener('click', toggle);
} else {
// A Declarative Shadow Root doesn't exist.
// Create a new shadow root and populate it:
const shadow = this.attachShadow({mode: 'open'});
shadow.innerHTML = ``;
shadow.firstChild.addEventListener('click', toggle);
}
}
}
customElements.define('menu-toggle', MenuToggle);