Javascript ways
Technical, Insightstitle: Javascript ways created_at: 2020-11-15T14:52:16.823Z updated_at: 2023-04-01T14:52:16.823Z tldr: Shorthands, macros, cannot understand, NaNaNaN whatever is_published: true star: false category: Technical, Insights share_type: share
Filter null, undefined
[1, 2, null, 5, undefined].filter(Boolean);
// [1, 2, 5]
Boolean
is an helper class, so Boolean(value)
return true
for all valid elements
Create an array of n
elements
const array = new Array(n).fill(0).map((_, i) => i);
Create an array with n
elements, fill it with 0
Add a helper prototype
Number.prototype.add = function (n) {
return this + n;
};
(1).add(2); // 3
Almost everything in JS is object, you can extend Number
, String
... like any other object
Calling functions with backtics
function saveName(name) {
this.db.save(name);
}
saveName`${this.firstName} ${this.lastName}`;
MDN Docs on Template literals
Finally doesn't wait
function foo() {
let r = 0;
try {
r = 1;
} finally {
r = 2;
}
return r;
}
foo(); // 2
The try catch finally
spec
Old school labels
cat: {
console.log("meow");
break cat;
console.log("woff");
}
// meow
// undefined
let x = [];
outter: for (let i = 0; i < 4; i++) {
inner: for (let j = 0; j < 4; j++) {
if (i + j === 2) {
continue outter;
}
x.push(i + j);
}
}
console.log(x); // [0, 1, 1, 3, 4, 5, 6]
labels work in javascript But, if you use it people around will beat you, seriously!
Noodles and curry
// basic currying
function makeAdderForA(a) {
return function (b) {
return a + b;
};
}
const adderFor_2 = makeAdderForA(2);
console.log(adderFor_2(3); // 5
// noodles, make me cook instantly!
(function () {
document.onreadystatechange = () => {
if (document.readyState === "complete") {
document.querySelector("html").classList.remove("veil");
}
};
})();
functions
returning functions is currying, and functions
invocating itself is IIFE. I call it noodels!
Infinite Pings
JS has a recursion limit of around 10000 calls, we can rely on generators to escape. Your browser will break, careful!
// Recursion error
function ping(n) {
console.log('ping', n);
return pong(n + 1);
}
function pong(n) {
console.log('pong', n);
return ping(n + 1);
}
// crash your browser
const actors = {};
const messageQ = [];
const postToMessageQ(name, msg) => messageQ.push([name, msg]);
const run => {
while (queue.length) {
const [name, msg] = queue.shift();
actors[name].next(msg);
}
}
function* ping() {
let n;
while (true) {
n = yield;
console.log('ping', n);
send('pong', ++n);
}
}
function* pong() {
let n;
while (true) {
n = yield;
console.log('pong', n);
send('ping', ++n);
}
}
actors.ping = ping();
actors.pong = pong();
send('ping', 0);
// ping 0
// pong 1
// ping 2
// pong 3
// ...
// to infinity and beyond!
You Don't Know JS: Async & Performance
Can't change me
Getting rid of type coercion
function nonCoercible(val) {
if (val == null) {
throw TypeError("nonCoercible shouldn't be called with null or undefined");
}
const res = Object(val);
res[Symbol.toPrimitive] = () => {
throw TypeError("Trying to coerce non-coercible object");
};
return res;
}
// objects
const foo = nonCoercible({ foo: "foo" });
foo * 10; // throws TypeError: Trying to coerce non-coercible object
foo + "evil"; // throws TypeError: Trying to coerce non-coercible object
nonCoercible(["foo"])[0]; // "foo"
Gist, Sergey Rubanov
Arrow functions needs shield to return objects
let f = () => {};
f(); // undefined
let f = () => ({});
f(); // {}
I used to mess this up so many times with react FC and .map
functions
Dei, you forgot a semicolon :|
Javascript insers a ;
token automatically
function foo() {
return;
1;
}
foo(); // undefined
function foo() {
return 1;
}
foo(); // 1
Rules of Automatic Semicolon Insertion
WTF
JS has character escape sequences
[666]["\155\141\160"][
"\
\143\157\156\163\164\
\162\165\143\164\157\
\162"
](
"\141\154\145\
\162\164(666)",
)(666); // alert(666)
alert from Hell
Function typings and merging
when function calls in Typescript are merged, the resulting argument list is an intersection not union
function funA(p: { apples: string; bannans: number }) {}
function funB(p: { apples: string; mangoes: string }) {}
const funC: typeof funA & typeof funB = ({ apples, mangoes }) => {};
// error: Property 'mangoes' does not exist
In typescript when we union objects the resulting is an superset of the object values, but when we union functions the resulting is the intersection on the function parameters. This is how all the type system work. Further reading difference between variance covariance and contravariance
Typescript enums to objects
TS has a really odd way of converting of enums to plain js
// with no variable assignee
enum THEME {
DARK,
LIGHT,
}
// in JS
var THEME;
(function (THEME) {
THEME[THEME["DARK"] = 0] = "DARK";
THEME[THEME["LIGHT"] = 1] = "LIGHT";
})(THEME || (THEME = {}));
// {0: "DARK", "DARK": 0, 1: "LIGHT", "LIGHT": 1}; so we can do THEME[0];
// but when you assign a string
enum THEME {
DARK = 'apple',
LIGHT = 'mangoes',
}
// in JS
var THEME;
(function (THEME) {
THEME["DARK"] = "Yagami";
THEME["LIGHT"] = "L";
})(THEME || (THEME = {}));
// {DARK:"Yagami", LIGHT: "L"}; we can't do THEME["L"]?
Component as function in react, wait wt?
You can use components as functions in react, store it in Objects and call it in render
const iconRecord = {
night: NightIconJSX,
day: DayIconJSX,
};
const App = () => {
return (
<div>
{object
.values(iconRecord)
.map((icon) => icon(/* you can pass in props as object {}*/))}
</div>
);
};
Further reading
Like it ?
Share with friends