Skip to main content

17 posts tagged with "javascript"

View All Tags

Math.imul()

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul

console.log(Math.imul(3, 4));
// expected output: 12

console.log(Math.imul(-5, 12));
// expected output: -60

console.log(Math.imul(0xffffffff, 5));
// expected output: -5

console.log(Math.imul(0xfffffffe, 5));
// expected output: -10

The reason imul exists is because it is faster in only one (so far) circumstance: AsmJS. AsmJS allows for JIT-optimizers to more easily implement internal integers in JavaScript. Multiplying two numbers stored internally as integers (which is only possible with AsmJS) with imul is the only potential circumstance where Math.imul may prove performant in current browsers.

Also: Why would I use Math.imul()?

strictEquals(a, b) without using "==="

Write a function called strictEquals(a, b) that returns the same value as a === b. Your implementation must not use the === or !== operators.

Solution: https://gist.github.com/gaearon/08a85a33e3d08f3f2ca25fb17bd9d638?ck_subscriber_id=920605104

function strictEquals(a, b) {
if (Object.is(a, b)) {
// Same value.
// Is this NaN?
if (Object.is(a, NaN)) {
// We already know a and b are the same, so it's enough to check a.
// Special case #1.
return false;
} else {
// They are equal!
return true;
}
} else {
// Different value.
// Are these 0 and -0?
if ((Object.is(a, 0) && Object.is(b, -0)) || (Object.is(a, -0) && Object.is(b, 0))) {
// Special case #2.
return true;
} else {
// They are not equal!
return false;
}
}
}

Flow: spreads don't preserve read-only-ness

type A = {| +readOnlyKey: string |};
type B = {| ...A, +otherKey: string |};

function test(x: B) {
x.readOnlyKey = 'overwrite'; // no error ?
x.otherKey = 'overwrite'; // no error ??
}

This applies to value spreads as well since they are creating a new object. It's less understandable for these type spreads where value spread is not involved.

Computing average in a constant time

Also known as average streaming.

Source: https://stackoverflow.com/a/22999488/3135248

The following function adds a number to an average. average is the current average, size is the current number of values in the average, and value is the number to add to the average:

double addToAverage(double average, int size, double value)
{
return (size * average + value) / (size + 1);
}

Likewise, the following function removes a number from the average:

double subtractFromAverage(double average, int size, double value)
{
// if (size == 1) return 0; // wrong but then adding a value "works"
// if (size == 1) return NAN; // mathematically proper
// assert(size > 1); // debug-mode check
// if(size < 2) throw(...) // always check
return (size * average - value) / (size - 1);
}

Difference between Object.preventExtensions/seal/freeze

All tested with node --use_strict (to prevent silent errors).

const obj = { a: 1 };
Object.preventExtensions(obj);
obj.b = 2; // TypeError: Cannot add property b, object is not extensible ❌
obj.a = -1; // ✅
delete obj.a; // ✅

Object.getOwnPropertyDescriptors(obj); // { a: { value: 1, writable: true, enumerable: true, configurable: true } }
const obj = { a: 1 };
Object.seal(obj);
obj.b = 2; // TypeError: Cannot add property b, object is not extensible ❌
obj.a = -1; // ✅
delete obj.a; // TypeError: Cannot delete property 'a' of #<Object> ❌

Object.getOwnPropertyDescriptors(obj); // { a: { value: 1, writable: true, enumerable: true, configurable: false } }
const obj = { a: 1 };
Object.freeze(obj);
obj.b = 2; // TypeError: Cannot add property b, object is not extensible ❌
obj.a = -1; // TypeError: Cannot assign to read only property 'a' of object '#<Object>' ❌
delete obj.a; // TypeError: Cannot delete property 'a' of #<Object> ❌

Object.getOwnPropertyDescriptors(obj); // { a: { value: 1, writable: false, enumerable: true, configurable: false } }

// You can basically only read:
console.log(obj.a);

Note: Flow tracks these flags on objects: frozen, sealed and exact.

Placement of catch BEFORE and AFTER then

Source: https://stackoverflow.com/questions/42013104/placement-of-catch-before-and-after-then

return p.then(...).catch(...);

// - vs -

return p.catch(...).then(...);

There are differences either when p resolves or rejects, but whether those differences matter or not depends upon what the code inside the .then() or .catch() handlers does.

What happens when p resolves

In the first scheme, when p resolves, the .then() handler is called. If that .then() handler either returns a value or another promise that eventually resolves, then the .catch() handler is skipped. But, if the .then() handler either throws or returns a promise that eventually rejects, then the .catch() handler will execute for both a reject in the original promise p, but also an error that occurs in the .then() handler.

In the second scheme, when p resolves, the .then() handler is called. If that .then() handler either throws or returns a promise that eventually rejects, then the .catch() handler cannot catch that because it is before it in the chain.

So, that's difference #1. If the .catch() handler is AFTER, then it can also catch errors inside the .then() handler.

What happens when p rejects

Now, in the first scheme, if the promise p rejects, then the .then() handler is skipped and the .catch() handler will be called as you would expect. What you do in the .catch() handler determines what is returned as the final result. If you just return a value from the .catch() handler or return a promise that eventually resolves, then the promise chain switches to the resolved state because you "handled" the error and returned normally. If you throw or return a rejected promise in the .catch() handler, then the returned promise stays rejected.

In the second scheme, if the promise p rejects, then the .catch() handler is called. If you return a normal value or a promise that eventually resolves from the .catch() handler (thus "handling" the error), then the promise chain switches to the resolved state and the .then() handler after the .catch() will be called.

So that's difference #2. If the .catch() handler is BEFORE, then it can handle the error and allow the .then() handler to still get called.

Should you use Node.js LTS or not?

Node LTS is primarily aimed at enterprise use where there may be more resistance to frequent updates, extensive procurement procedures and lengthy test and quality requirements.

Generally if you are able to keep up with the latest stable and future Node releases you should do so. These are stable and production ready releases with excellent community support. Unstable and experimental functionality is kept behind build and runtime flags and should not affect your day to day operations.

https://stackoverflow.com/a/34655149/3135248

Optional chaining gotchas

Optional chaining != error suppression operator.

(function () {
'use strict';
undeclared_var?.b; // ReferenceError: undeclared_var is not defined
arguments?.callee; // TypeError: 'callee' may not be accessed in strict mode
arguments.callee?.(); // TypeError: 'callee' may not be accessed in strict mode
true?.(); // TypeError: true is not a function
})();