If console.log(buf)
prints something like
<Buffer 7b 22 65 76 65 6e...
,
use console.log("%s", buf)
or
console.log(buf.toString())
.
For JSON data, I prefer the format of:
console.log("Received ", JSON.parse(myData));
to
console.log("Received %s", JSON.parse(myData));
because of the pretty colors, and because more of the nested types are displayed.
Append with push
Get FIFO element with shift
Get FILO element with pop
Do not use Date(seconds * 1000)
it is very different
from new Date(seconds * 1000)
Somehow I got it in my head that arrow function return behavior was
different
from explicit function return behavior. I thought one exited the outer
scope,
but that is incorrect. Observe:
function fn(callback) {
callback();
}
function main() {
fn(() => {
return;
});
console.log("You will see me");
fn(function() {
return
});
console.log("You will also see me")
}
main()
Use at
:
['a', 'b', 'c'].at(-1) // => 'c'
If I need an index:
const x = ['a', 'b', 'c'];
for (let i = 0; i < x.length; i++) {
console.log(x[i]);
}
If I don’t need an index:
const x = ['a', 'b', 'c'];
for (const y of x) {
console.log(y);
}
Use JSON.stringify
, the javascript equivalent of
python’s json.dumps
.
[1,2,3].filter(x => x >= 2)
Short for:
[1,2,3].filter((x) => x >= 2);
The sugary form of the arrow function only works if the closure takes
a single
argument.
[] == [] // false
[] === [] // false
For comparison with an empty array, use [].length
.
If using a jest matcher, use toEqual([])
for an empty
array.
!![] // => true
!!{} // => true
!!'' // => true
!!' ' // => false
!!1 // => true
!!null // => false
!!undefined // => false
[1] + [2] // => '12'
Use this instead
[1].concat([2]) // => [1,2]
Or, for array union
const x = [1, 2];
const y = [2, 3];
const z = new Set([...x, ...y]);
[...z] // => [1,2,3]
"hello".match(/^he/)
The equivalent of python’s x[1:]
is
x.slice(1)
class C {
myMethod() {
return 1;
}
get myGetter() {
return 2;
}
}
const c = new C()
c.myMethod() // => 1
c.myGetter // => 2
In ES6, methods are defined by only their name, e.g. there is no
additional func
or def
syntax to match
on.
This makes it hard to distinguish callsite from definition when grepping
a code base.
Use the pound sign. For example:
class C {
#myPrivateMethod() {
return 1;
}
}
const c = new C()
c.myPrivateMethod() // => Uncaught TypeError: c.myPrivateMethod is not a function
class C {
constructor(x) {
this.x = x;
}
}
If at the zero indent level, or whitespace padding unimportant:
const x = `hello
world`;
If at higher indent level:
const x = "hello\n" +
"world"
This will bite you if you pass fn pointers:
const x = {
y: 1,
z: function() { return this.y }
}
const fn = x.z
fn() // undefined!
Can fix it in a couple ways. I think this is most straightforward:
const x = {
y: 1,
z: function() { return this.y }
}
x.z = x.z.bind(x)
// Later...
const fn = x.z
fn() // 1
This is also OK, but I think it’s easy for the caller to forget the bind:
const x = {
y: 1,
z: function() { return this.y }
}
const fn = x.z.bind(x)
fn() // 1
Careful, this does not work as expected:
const o = new Object();
o.fn = (x) => {
this.fnCalledWith = x
}
o.fn("y")
o.fnCalledWith // undefined!!!
Use this instead:
const o = new Object();
o.fn = function(x) {
this.fnCalledWith = x
}
o.fn("y")
o.fnCalledWith // y
const [a, b] = [1, 2]
a // => 1
b // => 2
Buffers are reference types with reference semantics.
Strings are reference types with value semantics.
So while this works as expected:
"x" == "x" // => true
this is a surprise:
Buffer.from('x') == Buffer.from('x') // => false
Use this instead:
Buffer.from('x').equals(Buffer.from('x')) // => true
Or:
Buffer.compare(Buffer.from('x'), Buffer.from('x')) // => 0
const a = {a: 1};
function f(x) {
x[‘b’] = 2;
}
f(a);
a; // => {a: 1, b: 2}
Use this as protection:
const a = {a: 1};
function f(x) {
x = {…x};
x[‘b’] = 2;
}
f(a);
a; // => {a: 1}
This does not do what I expect:
const keyName = "hello";
let hash = {
keyName: "world"
}
I want:
const keyName = "hello";
let hash = {
[keyName]: "world"
}
Try to use async/await where possible instead of callback code.
With async/await, I can have assurances that my try/catch statements
will
work without much thought. By contrast, if a callback slips in (which is
easy), suddenly I need to think hard about catching errors or the
process can crash out.
try {
setImmediate(() => {
throw new Error();
});
} catch (e) {
// catch error.. doesn't work
}
Example sourced from https://bytearcher.com/articles/why-asynchronous-exceptions-are-uncatchable
if (new Boolean(false)) {
console.log("yes, you see me")
}
Better to use semi-colons. This throws an exception:
console.log("a")
(async () => {})()
But this doesn’t
console.log("a");
(async () => {})()
Because the syntax is ambiguous without the semicolon. It could be
interpretted
as console.log('a')(async() => {})
, e.g. treating the
return of console.log()
as a function
// Throw in an async func. Does the outer try/catch catch the error? No!
try {
(async () => {
throw Error("You won't catch me");
})();
}
catch {
console.log("Never seen");
}
__name__ == '__main__'
Specifically for node. CommonJS only. This does not work with mjs:
if (require.main === module) {
// run me
}
For mjs, I use a workaround like:
if (process.env.TESTRUN == "1") {
// run me
}
And run with TESTRUN=1 node myfile.mjs
In a repl:
Object.getOwnPropertyNames(myVar)
Object.keys(myVar)
Date.now()
returns milliseconds since
unix epoch in the target system’s clock, excluding leap seconds
Sleep for 100 ms:
await new Promise(r => setTimeout(r, 100))
These two are the same:
await new Promise(r => setTimeout(r, 100))
await new Promise((r) => { setTimeout(r, 100) })
const x = "hello"
const y = "world"
{x, y}
# => { x: 'hello', y: 'world' }
const a = {
b(c) {
return `hello ${c}`
}
}
a.b("world")
# => "hello world"
Option A:
// a.js
const xyz = "a"
export default xyz
// Use site:
import a from './a.js'
Option B:
// b.js
export const b = "b"
// Use site:
import { b } from './b.js'
Contents of index.html
```
<html>
<body>
<script type="module">
import { greet } from './my-module.js';
greet('world');
</script>
</body>
</html>
```
Contents of my-module.js
export function greet(name) {
alert(`Hello, ${name}!`);
}
Serve index.html
with
python -m http.server 8000
and then browse to
localhost:8000
// In mjs
export const handler = () => {}
// In cjs
const handler = () => {
}
module.exports.handler = handler
This is a quick ballpark. Use a benchmark with large sample if true cost is desired:
import { performance } from 'perf_hooks';
const t1 = performance.now()
// myFn()
const t2 = performance.now()
console.log(`Execution time: ${(t2 - t1).toFixed(3)} milliseconds`);
x in y
It does not do what I intuitively think it does. For example:
1 in [1,2,3] # => true, but this is misleading
'a' in ['a', 'b', 'c'] # => false
What I actually want is:
['a', 'b', 'c'].includes('a')
for x in y
, for in
Be careful with for x in y
construct, x
will be the index!
Use for x of y
instead.
var x = Array(2).fill([0])
x[0][0] += 1
x
# => [ [ 1 ], [ 1 ] ]
Object.keys(mydict)
typeof(myVar)
console.log(myVar.constructor)
console.log(myVar.constructor.name)
const x = 'hello'
console.log(`${x} world`)
function x(y) {
console.log(y)
}
fn = (y) => {
console.log(y)
}
var myObj = {
someProperty: "hello",
someFunction: function() {
return this.someProperty + " world"
}
}
Map
Gotcha: note the parameter order in the ForEach closure.
const propMap = new Map()
propMap.set('a', 'foo')
propMap.set('b', 'bar')
propMap.forEach((value, key) => {
console.log(`${key} -> ${value}`)
})
// Prints
// a -> foo
// b -> bar
I was looking for something like swift’s didSet
:
var myObj = {
set aProperty(newValue) {
console.log("changing from " + this._aProperty + " to " + newValue)
_aProperty = newValue
},
_aProperty: "foo"
}
myObj.aProperty = "bar" // Prints "changing from foo to bar"
jsc
on
MacOSAs of Sonoma 14.2, jsc
is at
/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc
I symlink it with:
ln -sv /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc /usr/local/bin/jsc