TC39: Some interesting things already in stage 4(finished)

I know all the proposals are of course very helpful in code development but these are the few things that really got my attention
Numeric Separators
After im reading about this proposal this is a really help in the future because we can maximize the use of numbers using separator. According to this proposal is merge between an earlier draft proposal-numeric-underscores, to extend the existing NumericLiteral to allow a separator character between digits.
In finance system to make sure every digits are very important and how fixed that. Large numeric literals are difficult for the human eye to parse quickly Lets see this number
1000000000 // Is this a billion? a hundred millions? Ten millions?
Using underscores (_
) as separators helps improve readability for numeric literals, both integers and floating-point (and in JS, it's all floating-point anyway):
1_000_000_000 // Ah, so a billion
101_475_938.38 // And this is hundreds of millions
let fee = 123_00; // $123 (12300 cents, apparently)
let fee = 12_300; // $12,300 (woah, that fee!)
let amount = 12345_00; // 12,345 (1234500 cents, apparently)
let amount = 123_4500; // 123.45 (4-fixed financial)
let amount = 1_234_500; // 1,234,500
String padding
Discussed about way to pad a string using native methods, working with JavaScript strings today is more painful than it should be. Bringing this into the platform will improve performance of the web, and developer productivity as they no longer have to implement these common functions.
Discussed about Semantics of min length vs max length, how determine first parameter should determine the minimum length or the maximum length of the padded string lets see below example
'foo'.padEnd(4, '12') // foo12 (min length)
'foo'.padEnd(4, '12') // foo1 (max length)
Left padding, with respect to the fill string: consistency with other languages
"abc".padStart(10, "0123456789") // 3456789abc
"abc".padStart(10, "0123456789") // or whereas taking the first part gives 0123456abc
Top-level await
Talk about asynchronous until today it is complicated but is very challenging and maybe this feature can some fixed the many problem that exists. With top-level await
, ECMAScript Modules (ESM) can await
resources, causing other modules who import
them to wait before they start evaluating their body.
Top-level await
lets us rely on the module system itself to handle all of these promises, and make sure that things are well-coordinated. This is could be simply written and used as follows:
// awaiting.mjs
import { process } from "./some-module.mjs";
const dynamic = import(computedModuleSpecifier);
const data = fetch(url);
export const output = process((await dynamic).default, await data);
// usage.mjs
import { output } from "./awaiting.mjs";
export function outputPlusValue(value) { return output + value }
console.log(outputPlusValue(100));
setTimeout(() => console.log(outputPlusValue(100), 1000);
usage.mjs
will execute until the await
s in awaiting.mjs
have had their Promises resolved, so the race condition is avoided by design. This is an extension of how, if awaiting.mjs
didn't use top-level await
, none of the statements in usage.mjs
will execute until awaiting.mjs
is loaded and all of its statements have executed
RegExp Named Capture Groups
A capture group can be given a name using the (?<name>...)
syntax, for any identifier name
. The regular expression for a date then can be written as /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u
. Each name should be unique and follow the grammar for ECMAScript IdentifierName.
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
console.log(`one: ${one}, two: ${two}`); // prints one: foo, two: bar
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';
Let’s see this actually might be very helpful how to make grouping of items easier and maybe we use it very often
WeakRefs
A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent (i.e. an object which is referred to by a weak reference) are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed, the weak reference may return the object even if there are no strong references to it.
For example, if you have a number of large binary image objects (e.g. represented as ArrayBuffer
s), you may wish to associate a name with each image. Existing data structures just don't do what's needed here:
- If you used a
Map
to map names to images, or images to names, the image objects would remain alive just because they appeared as values or keys in the map. WeakMap
s are not suitable for this purpose either: they are weak over their keys, but in this case, we need a structure which is weak over its values.
function makeWeakCached(f) {
const cache = new Map();
return key => {
const ref = cache.get(key);
if (ref) {
const cached = ref.deref();
if (cached !== undefined) return cached;
}
const fresh = f(key);
cache.set(key, new WeakRef(fresh));
return fresh;
};
}
var getImageCached = makeWeakCached(getImage);
But this technique is still incomplete. This technique can help avoid spending a lot of memory on ArrayBuffer
s that nobody is looking at anymore, but it still has the problem that, over time, the Map
will fill up with strings which point to a WeakRef
whose referent has already been collected.
Reference:
Proposal Stages — Stage 4. (n.d.). https://www.proposals.es/stages/stage4