sahilrajput.com

Learn Javascript

Quick Links:

❤️ Javascript Cheatsheet - Sahil

Click here

Geeter, Setters in Object

drawing

😇 How is console.log and console.error different in nodejs? (ChatGPT)

Click here (Google Doc)

Disadvantages of structuredClone? (ChatGPT)

Note: I found about it in svelte’s docs here

The structuredClone method, which deep-clones JavaScript objects, has several potential drawbacks, despite its convenience:

Limited Browser Support: While structuredClone is widely supported in modern browsers, older browsers (like some versions of Internet Explorer) do not support it, which could be an issue for applications needing compatibility with legacy systems.

Performance Overhead for Large Objects: structuredClone may be slower than alternatives (such as manual deep cloning) when handling very large or complex objects, as it has to replicate each property and handle circular references. For simple objects, the performance difference may not be noticeable, but with deeply nested or large objects, it could lead to noticeable delays.

Serialization Constraints: structuredClone only works with data types that are serializable in JavaScript. This means it cannot clone objects with:

Loss of Prototypes and Methods: The cloning process strips away prototypes, methods, and non-enumerable properties, meaning that if you rely on methods or class instances, they won’t carry over to the cloned object. Only pure data objects (without methods) are fully compatible.

Potential for Silent Errors: Because it throws errors when encountering non-cloneable data types, developers need to catch these errors. Otherwise, structuredClone may fail silently if not handled, leading to debugging challenges.

Limited Support for Circular References: While it supports circular structures in arrays and objects, certain complex circular references may not clone as expected, requiring additional handling.

For cases that need method retention, prototype inheritance, or support for non-serializable values, alternative approaches, like libraries (e.g., Lodash’s cloneDeep), custom cloning functions, or JSON serialization (if limited to simple objects), might be more suitable.

Math.trunc(…)

Source - MDN

Unlike the other three Math methods: Math.floor(), Math.ceil() and Math.round(), the way Math.trunc() works is very simple. It truncates (cuts off) the dot and the digits to the right of it, no matter whether the argument is a positive or negative number.

console.log(Math.trunc(13.37));
// Expected output: 13

console.log(Math.trunc(42.84));
// Expected output: 42

console.log(Math.trunc(0.123));
// Expected output: 0

console.log(Math.trunc(-0.123));
// Expected output: -0

Math.trunc(-Infinity); // -Infinity
Math.trunc("-1.123"); // -1
Math.trunc(-0.123); // -0
Math.trunc(-0); // -0
Math.trunc(0); // 0
Math.trunc(0.123); // 0
Math.trunc(13.37); // 13
Math.trunc(42.84); // 42
Math.trunc(Infinity); // Infinity

ChatGPT says its okay to mix await and catch keywords

My tests works too:

image

image

Learn global error handling

process.on("unhandledRejection", (err) => {
	console.log('caught rejection')
	console.log('error?', err)
})

async function main() {
	throw 'rock paper scissor'
}
main()
# Output:
caught rejection
error? rock paper scissor

??=, ||= and &&= operators

// assings only if the variable is null or undefined
??=

// assigns if null, undefined or any other falsy value
||=

// assigns only if the value already exists
&&=


# Examples:
let car
car ??= 'bar'
// car is now 'bar'

let bat = ''
bat ||= 'something'
// now bat is 'something'

let cat = '   some test with spaces on both sides   '
cat &&= cat.trim()
// now cat is just 'some test with spaces on both sides'

Merge duplicates with reduce array method

Learn: reduce method creates a item i.e, accumulator and does not mutate the original array at all.

Source: A comment in this answer: Click here

let arr = [
  { name: 'John', contributions: 2 },
  { name: 'Mary', contributions: 4 },
  { name: 'John', contributions: 1 },
  { name: 'Mary', contributions: 1 }
];


// we reduce our `arr` array to get `reduced array` i.e., output
let output = arr.reduce(function(accumulator, cur) {
  let found = accumulator.find((elem) => elem.name == cur.name);
  if (found) found.contributions = found.contributions + cur.contributions;
  else accumulator.push(cur);
  return accumulator;
}, []);

console.log(output) // [{"name": "John","contributions": 3},{"name": "Mary","contributions": 5}]

Why use Object.is(a,b) instead of === to check if values are equal?

Source: Click here

// pros of Object.is() method
Object.is(-0, +0); // => false
Object.is(NaN, NaN); // => true

// cons of tripple equality operator
-0 === +0; // => true
NaN === NaN; // => false

Are indices/keys returned in for..in loop of string type?

Yes, they are! This is unexpected to most people though, but typescript will sail your boat for sure. Love typescript!

image

Are string objects?

No, but they can be explored using using object methods.

image

String act as array with index and values like that:

image

Object.assign()

TLDR: Its amazing. Source: Comment on SO Question Click here

const name = 'David'
const person = { name : 'sahil' }

// instead of doing
person.name = name

// ❤️ you can simply do
Object.assign(person, { name })
// Object.assign(window, { person }) // this is equivalent to `window.person = persons`

// ❤️
Object.assign(window, { person }).person // this prints updated value of `window.person`

Modules

import defaultExport, * as name from "module-name";
import defaultExport, { export1 } from "module-name";
const { default: myDefault, foo, bar } = await import('/modules/my-module.js');



// Anonymous
let myObject = {
  field1: value1,
  field2: value2
};
export {myObject as default};

// above export is equivalent to below:
export default {
  field1: value1,
  field2: value2
};
src: [Import in js MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports)

Simple example usage of js modules from ST Answer

Source: Click here

// values/value.js
let a = 1;
let b = 2;
let c = 3;

export {a, b, c};
// values/index.js
import * as values from './value';

export default values;
export * from './value';
// index.js
import values, {a} from './values';

console.log(values, a); // {a: 1, b: 2, c: 3} 1

Enable ecma modues with nodejs

Desirable way: node --input-type=module test.js. Refer here for all ways to do this: [Enabling ESM Official Docs](https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_enabling). Also, tho use node test.mjs if the former seems to much. And do read about the awesomeness of convention of file extensions standard which is also followed in browsers as well and thus actualy good for real.

Serial and parallel asynchronous execution in javascript/nodejs

I love Promise.allSettled more that I hate try{}catch(e){} syntax

read more @ https://javascript.info/promise-api#summary

let b = () => Promise.reject(20)

await Promise.allSettled([b()])
// ouput: keyPoint: It never throws error(i.e., `reject("someErrorMessage")`. Yikes!
[
    {
        "status": "rejected",
        "reason": 20
    }
]
So, now you would be tempting to re-write all your previous `try{}catch(e){}` flavoured in a more if/else like manner, don't you .?

// I mean instead of writing:

try{
    const res = await fetch('ss')
    await res.json()
}catch(e){
    console.log('Caught program control thief :LOL: ~sahil~\n', e)
}
// ouput:
Caught program control thief :LOL: ~sahil~
 SyntaxError: Unexpected token < in JSON at position 0

// you can write more synchronouse looking code, e.g.,

let res = await fetch('ss')
let [settledRequest] = await Promise.allSettled([res.json()])
if(settledRequest.status === 'fulfilled') console.log('yikes, got value', settledRequest.value)
if(settledRequest.status === 'rejected') console.log('shit, got reason', settledRequest.reason)
// isn't that the way you wanted code to be written like from a long time...?

Promsise.all vs. Promise.allSettled (i.e., either resolved or rejected)

let a = () => Promise.resolve(10)
let b = () => Promise.reject(20)

// Promise.allSettled
await Promise.allSettled([a(), b()])
// output: keyPoint: It never throws error so we can use it without try and catch(what a godly thing, isn't it ?).
[
    {
        "status": "fulfilled",
        "value": 10
    },
    {
        "status": "rejected",
        "reason": 20
    }
]

// Promise.all
try{
    await Promise.all([a(), b()])
}catch(e){
    console.log('boom', e)
}

// output:
boom 20