An Interest In:
Web News this Week
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
- March 14, 2024
A few handy JavaScript tricks
I'd like to document a few neat JavaScript tricks and patterns I've recently learnt from Twitter and other online resources (which I sadly haven't kept track of). All the credits go to the online JavaScript community.
Invoking an IIFE (Immediately Invoked Function Expression) without extra brackets
We can use the void
operator for that, where void
clearly indicates we want to discard the result of an expression (which an IIFE itself is):
void function debug() { if (confirm('stop?')) debugger;}();
I believe it's more readable and mnemonic than wrapping the function with brackets:
(function debug() { if (confirm('stop?')) debugger;})();
If we do need the result:
const rgb = function getColor(color) { return { red: '#FF0000', green: '#00FF00', blue: '#0000FF' }[color];}(car.color);
Invoking an async
IIFE (Immediately Invoked Function Expression)
Similarly to the above, we don't need the wrapping brackets:
await async function delay() { const start = performance.now(); await new Promise(r => setTimeout(r, 1000)); console.log(`elapsed: ${performance.now() - start}`);}();
Destructuring of a function argument inline:
function output ({firstName, lastName}) { console.log(firstName, lastName);}const person = { firstName: 'Jane', lastName: 'Doe'};output(person);
Partial destructuring of a function argument inline:
function output ({firstName, ...rest}) { console.log(firstName, rest.lastName, rest.age);}const person = { firstName: 'John', lastName: 'Doe', age: 33};output(person);
Using expressions in switch
const category = function getCategory(temp) { // the first `case` which expression is `true` wins switch(true) { case temp < 0: return 'freezing'; case temp < 10: return 'cold'; case temp < 24: return 'cool'; default: 'unknown'; }}(10);
Passing a non-function object as event handler to addEventListener
The trick is to implement EventListener.handleEvent
:
const listener = Object.freeze({ state: { message: 'Hello' }, handleEvent: event => { alert(`${event.type} : ${listener.state.message}`); }});button.addEventListener('click', listener);
Checking if an object is String
(Number
, Boolean
, Object
)
Could you predict which console output is common for s1
and s2
snippets below? I myself couldn't, so I've made it a runnable RunKit:
const s1 = 's'; log('s1 instanceof String');log('typeof s1');log('s1.constructor === String');const s2 = new String('s'); log('s2 instanceof String');log('typeof s2');log('s2.constructor === String');function log(code) { console.log(`${code}: ${eval(code)}`); }
Interestingly, it's s1.constructor === String
and s2.constructor === String
, both are true
. It's even more fun with TypeScript, and it may feel odd for a person coming to JavaScript with C# or Java background.
So, to check if variable s
represents a string, the following works consistently for primitive values and their wrapping class types:
const isString = s.constructor === String;
We can also make it work across realms (an iframe
or a popup):
const isString = s.constructor.name === 'String';
A mnemonic way of ignoring promise errors (where applicable):
await promise.catch(e => void e);
This literally says: "void that error" and it's ESLint-friedly. I see it becoming increasingly useful, to avoid potential troubles with unhandled promise rejections in Node v15+. For example:
// f1 has to start before f2const promise1 = f1();const promise2 = f2();// we need promise2 results first and// we don't care about promise1 results if promise2 fails,// so let's prevent unwanted unhandledrejection for promise1promise1.catch(e => void e); // observe promise2 resultsawait promise2; // now observe promise1 results, after promise2await promise1;
Thenables can be useful side-by-side with promises
I've previously blogged about thenables. In a nutshell:
function createDeferred() { let resolve, reject; const promise = new Promise((...args) => [resolve, reject] = args); return Object.freeze({ resolve, reject, then: promise.then.bind(promise) });}const deferred = createDeferred();// resolve the deferred in 2s setTimeout(deferred.resolve, 2000);await deferred;
Tell which promise settles first in Promise.race
Sometimes we need to know which promise became resolved or rejected first and thus won the race with Promise.race
, similarly to Task.WhenAny
in .NET. Linking my SO answer:
/** * When any promise is resolved or rejected, * returns that promise as the result. * @param {Iterable.<Promise>} iterablePromises An iterable of promises. * @return {{winner: Promise}} The winner promise. */async function whenAny(iterablePromises) { let winner; await Promise.race(function* getRacers() { for (const p of iterablePromises) { if (!p?.then) throw new TypeError(); const settle = () => winner = winner ?? p; yield p.then(settle, settle); } }()); // return the winner promise as an object property, // to prevent automatic promise "unwrapping" return { winner }; }
Hope this is useful
I'll be updating this post as I learn more. Follow me on Twitter if interested in these updates.
Original Link: https://dev.to/noseratio/a-few-handy-javascript-tricks-an9
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To