There are some nice ideas here, but how many different ways do you need to do something? Since JavaScript has an especially high burden for backward compatibility you can’t really remove old cruft, and adding yet another way to (whatever) just makes the language harder to learn and harder to read.<p>Warts and all, one of the best things about ES5 and earlier is that the language was so simple that you could pick it up in a day.<p>The later additions have added developer convenience for sure, but at the expense of taking something simple, consistent, and very easy to read, and turning it into a complex and subtle language with a lot of redundant syntax. For example all the different syntaxes for defining a function with the subtle differences between them. And in this articles proposal - since switch doesn’t do what I want, we’ll have both switch AND case with different semantics and syntax. Ugh.<p>At this point I’d rather see an effort to deprecate cruft or standardize features over throwing in new things.
I'd like a decent standard library.<p>These days I work mainly with C#, and to a lesser extent Typescript and JavaScript - the anemic nature of the ECMAScript standard library is really jarring.
I may have overlooked it, but I want actual proper integers. Not doubles, just integers.<p>I also missed the awesome bind-operator. EG:<p><pre><code> const getFoo = () => this.foo;
const bar = { foo: 1 };
console.log(bar::getFoo()); // 1
</code></pre>
<a href="https://github.com/tc39/proposal-bind-operator" rel="nofollow">https://github.com/tc39/proposal-bind-operator</a>
There's some interesting stuff in here, but I'm noticing a large chunk of it is syntactic sugar.<p>Keeping the extensible web manifesto in mind, I wonder if maybe what we really want is to have some kind of standardization around transpiling code.<p>With new features like promises, we had extensive testing via user libraries before they made their way into the language. But with these kinds of syntactic features, that doesn't seem to be happening.<p>If a feature is almost purely syntactic sugar, maybe it would make more sense for it to be supplied via a transpiler rather than being baked into the core language? Are there pain points or disadvantages to libraries like Babel that we could address via the core language instead?
As someone who teaches JS on the side, I'm literally scared of the idea of introducing another construct called "case." Especially one that goes in the opposite place of where the "case" normally does: "switch ... case" vs. "case ... when."<p>JavaScript is already jam packed with subtleties and gotchas that make it hard to learn, including situations where two things have the same name or the name doesn't quite match the underlying concept: C-style "for" vs. "for ... in" vs. "for ... of," object vs. Object, Object.prototype vs. "the prototype of the object," etc. We don't need another one of those.<p>I'd actually like this if it used another word than "case." "choose ... when", maybe? Kinda awkward, but I bet someone could think of something better. "case" has the nice feature that it's already a reserved word, but it's not valid syntax to have a variable name right next to an open brace, so the parsers could figure it out.
Is it just me or are those really making Javascript weirder?<p><pre><code> const func = do {
let result;
() => {
if (result === undefined) {
result = someComputation();
}
return result;
};
};
</code></pre>
Shouldn't that be "if (result === undefined) then someComputation else result"? Why import functional style and proceed to make it inherently imperative with a return in the middle of the block?<p><pre><code> obj?.foo?.bar?.baz
</code></pre>
The point of optional chaining is that you can place functions within the chain. That seems to be a very surprising and useless way to do them.
Javascript is still missing simplicity, consistency and a unified core set of ideas. It will always be that way too.
Javascript will always be something grudgingly accepted or used with some misgiving. ES6 has some very nice features and the good parts of javascript stand out as much as the unfortunate inconsistencies lurking inside the language. People know how to use it. Some use it quite well but I always get the feeling I have to step around carefully and not make a dumb mistake in js which is easier to do than almost any other language except say PHP. Web assembly should open up some badly needed possibilities. All we really need is a consistent API. A world without js? I hope so.
I was tempted to cite Antoine de Saint-Exupéry's quote on perfection, but we all know that, right?<p>But then again, even the author mentions at the beginning the "risk of adding too much" and, well, I wonder if this has not already happened to JavaScript.
I feel like there's something I'm missing with do expressions. Are they purely syntactic sugar? What can I do with a do expression that I can't do with an immediately invoked anonymous function?<p>The examples the article gives don't really look all that syntactically different to me.<p><pre><code> const func = (() => {
let result; // cache
return () => {
if (result === undefined) {
result = someComputation();
}
return result;
}
})();
const func = do {
let result;
() => {
if (result === undefined) {
result = someComputation();
}
return result;
};
};
</code></pre>
And I guess I wouldn't be able to recurse in a do expression like I can with a named function? So it's not like I can actually universally stop using immediately invoked expressions everywhere.
A lot of great and well-thought-out suggestions here. Whenever taking deeper dives into Javascript, I tend to find myself on 2ality.com though google searches and whatnot. They do well when it comes to breaking down the language and features.<p>I'm a fan of 2.2: destructuring switch, although I occasionally employ something similar in JavaScript and other languages with a `switch` statement:<p><pre><code> const resource = await fetch(jsonService);
switch (true) {
case resource.status === 200:
console.log(`size is ${resource.headers['Content-Length']}`);
break;
case resource.status === 404:
console.log('JSON not found');
break;
case resource.status >= 400:
throw new RequestError(res);
break;
}
</code></pre>
It's missing the destructuring aspect, so the first case is a bit more verbose, and I imagine there's better potential to optimize something like the OP's example. But it has a similar effect to the example and works today.<p>Slightly related: I really wish `case` worked with brackets instead of break, similar to OP's example. It looks cleaner and is easier to visually parse. I suppose that's only better if you prefer brackets (which I do).
I would like a null conditional operator and null coalescing operator.<p>return data?.error?.message ?? "no error";<p>Also pattern matching would be a big win.
What's really missing from javascript?<p>1. The ability to run my code without transpiling and reinstall dependencies for 10 minutes.<p>2. The ability to know which of the last 5 version of javascript to use.<p>3. Stability in my dependencies.<p>4. Consolidation and standardizing on established frameworks.<p>Basically undoing all the mess the ecosystem has done over the last 8 years.
I know it will never happen, but something like LINQ in C#. Not just functions that iterate over collections, but the whole idea of language integrated queries where code is turned into expression trees that can be parsed and translated by providers.<p>For instance in C# you can take the same LINQ expressions and they can be translated to sql by EF or MongoQuery by the Mongo driver at runtime.
As an aside, I’m not seeing any novel features in this list. All of them seem to be borrowed from other languages (Swift, F#, Haskell, ...).<p>With enough of this, at what point will all languages start to look identical (Youngme Moon calls this “homogeneous heterogeneity”)?<p>And how often does a language come along that introduces something truly new, rather than porting an idea from another popular language?
Here are things that I've added in Sciter's script (<a href="https://sciter.com" rel="nofollow">https://sciter.com</a>):<p>'like' operator that is used as a match<p><pre><code> if( obj like /[A-Z]/g ) … // "string".match
if( obj like {name:String} ) … // obj has name string field
if( obj like [String,Object] ) … // obj is an array of at least two elements, string and object.
</code></pre>
extended switch() :<p><pre><code> switch(obj) {
case 1: … // standard JS
like /[A-Z]/g: … // RegExp, Object, Array match
instanceof cls: … // obj instanceof cls
in [1,2,3]: … // obj
}</code></pre>
1.1 Comparing objects by value
I _think_ I'd prefer a standard `equals` method, or more likely a `[Symbol.equals]` method. With `[Symbol.equals]` and `[Symbol.hash]` we could also build collections for objects.
After messing with Elixir for a while, i really enjoyed the piping feature. I’m sure it will be added to js and I’m genuinely excited cause it makes reading code easier for me, given that your function names tell you what the function does
I wish more languages follow the sense of being fun to code like ruby.<p>[1, 2, 3] - [1, 3]
#Yields [2]<p>The code is readable, intuitive and short yet many languages never have this simplicity.<p>JS example.
<a href="https://stackoverflow.com/questions/1187518/how-to-get-the-difference-between-two-arrays-in-javascript" rel="nofollow">https://stackoverflow.com/questions/1187518/how-to-get-the-d...</a>
What we really need isn't more syntax, it's core features like threads, operator overloading, a large std library, some real form of serialization (JSON doesn't come close to counting), etc.
IMHO the list of changes presented here sort of half way gets you there to the (apparently) platonic ideal of being more swift or Kotlin like. It's better but seems a bit lacking in ambition because of backwards compatibility.<p>I'd argue backwards compatibility is actually a lot less important in the JS world than it currently appears to be. Why not aggressively deprecate all the uglyness, broken semantics, etc. If you write ES 2020, or whatever they will call it, why would you still want broken floating point math, wacky equals behavior that nobody can explain with a straight face, etc. Just deprecate it, start disallowing it, and eventually remove it from the language in a couple of versions.<p>Browser javascript is effectively a compilation target these days. Yes you can write in it directly but many people don't do that. Transpilers seem to be the norm these days. Mostly transpilers already do work around javascript legacy but they still have to deal with hiding some of the ugliness.<p>The good news is that people update their browsers. So there is very little need for transpilers to be able to target old versions of browsers. Mostly they just need to deal with current and recent versions.<p>With the emergence of WASM, that is becoming a more obvious compilation target. You can already run C, Kotlin, Rust, Code, etc. using it. Doing so, you bypass all of the legacy of javascript. It's just another compilation target for compilers.<p>It's not such a big leap to simply run javascript interpreters/vms on top of WASM as well. Why not? It's not any different from doing the same with ruby or python. It would be a great way to support legacy applications and it completely removes the need for javascript to continue to support legacy features. IMHO, it would greatly simplify browser implementations if all they had to do is support running WASM + whatever standardized bindings they ship for things like the DOM, browser storage, webgl, etc.<p>You could freeze a current version of v8, call it legacy js and use that to run legacy javascript if/when you actually need it and rely on a modern JS interpreter without any of the baggage. My guess is that running legacy js would very rapidly become a niche thing.
A built-in way to conveniently iterate n times.<p>Anyone have a sensible pure JavaScript example for:<p><pre><code> range(5).forEach(fn)
</code></pre>
I haven't found one that felt small enough to use inline. It end up using traditional for loops.
For value equality, I feel like the whole value/reference type distinction is an unnecessary distraction. What we really need is different <i>operators</i> to handle object identity comparisons and value comparisons. Whether an object can be meaningfully compared by value to another object is orthogonal to whether it's a value type or not - e.g. arrays are reference types, but there's no reason why any two arrays can't be compared element-by-element.<p>One language that gets it mostly right is Python, where "==" always compares values, and "is" always compares references. Thus, you can use either for e.g. lists and sets, depending on what you actually need at any given time. However, Python fails in that it doesn't give the same flexibility in many contexts where the comparisons are implicit - e.g. in dicts and sets (it always uses ==, instead of letting the user specify an equality function).<p>Ironically, a language that gets it fully right - including the standard library - is VB.NET.<p>I'm not even sure that value types themselves are such a useful concept. A value type can be thought of as an immutable reference type, where any mutations done via the reference simply cause a new object to be created and the reference changed (semantically; under the hood, it can be easily optimized down to in-place update).
In this code please remove the when keyword if possible. It's only noise. The Elixir equivalent works well without it. Other than that I'd love that kind of pattern matching on JavaScript.<p><pre><code> case (resource) {
when {status: 200, headers: {'Content-Length': s}} -> {
console.log(`size is ${s}`);
}
when {status: 404} -> {
console.log('JSON not found');
}</code></pre>
Reminds me of this quote:<p>“Perfection is achieved when there is nothing left to take away.” --Antoine de Saint-Exupéry<p>This principal should be applied more to programming languages.
why no one proposes as feature a header to make javascript strict with the newest standard and deprecate and drop compatibility from previous versions in the newer ones?<p>Or even just complete support for asmjs with interop and program in completely other languages, especially since the person who wrote this seems to want to program in languages with different semantics...
Much of this reads like the author wants JavaScript to be something it isn't. The requests for compare-by-value data structures, immutability, and true concurrency are huge paradigm shifts from the heart of the language whose implementation would no doubt come with significant complexity overhead.
I love these proposals and while it probably makes sense for me to learn more about the languages that already implement it there's no denying that having them in JS is a win. =)<p>I wish I knew about python's [itertools](<a href="https://docs.python.org/3/library/itertools.html" rel="nofollow">https://docs.python.org/3/library/itertools.html</a>) before I started making [streaming-iterables](<a href="https://www.npmjs.com/package/streaming-iterables#api" rel="nofollow">https://www.npmjs.com/package/streaming-iterables#api</a>) for example.
Not sure if it had been mentioned already, but I think we could benefit from cancellable Promises.<p>Many of the modules and libraries currently support Promises, and `async/await`, but try to find a way to cancel a long-running Promise. Some libraries have resorted to using their own mechanisms, and some (e.g. `axios`) resorted to using a withdrawn TC39 proposal.<p>I'd like a standard, easy way to cancel a Promise. I know it's not simple, and Promises can wrap around other Promises, etc. but if I'm e.g. uploading a large file to a server, there should be an easy way to provide my users with a "cancel" button that works.
Types :) I tend to use underscore for just _.get or _.set these days as I have most everything else I want so having some built in way to do that would be nice but the elephant in the room here is the toolchains being built quietly behind the scenes that support web assembly from strongly typed languages with much better load times and performance. The WALT one and the oCaml React one is pretty cool but would be nice if there was an official strong-typed JavaScript version for this scenario being built as a spec.
Entirely off-topic (or maybe not given the nature of like 20% of the comments here), but it's getting seriously annoying how in <i>every</i> thread even tangentially related to programming there are ten or so people (not the same people, not trying to call anyone out) trying to proselytize about functional programming and/or static typing.<p>They're <i>not</i> panaceas, they're just alternative approaches to programming no worse nor <i>better</i> and they don't need to be brought up in every. Single. Post.
JavaScript still is often extended via inheritance, such as classes and modules. This is unfortunate because inheritance is the opposite of simple, putting things together instead of taking them apart.<p>One addition that could greatly improve simplicity is assignable blocks. A block provides scope, much like a function, but accepts no input and returns nothing. Most functions I write take no input and return undefined because I only need them for code reuse by reference.<p>Imagine code like this:<p><pre><code> if (expression) myBlock else otherBlock;</code></pre>
Renderer access. It should be possible for js to control and get callbacks for rendering and event updates in styling. Though that's a browser feature, not really js
I'd like to see a real, useful implementation of weak references, for use in value caches, or a way to manually take over garbage collection for some objects.<p>Basically if I want to keep a cache of expensive objects that will grow monotonically, I need to do a lot of work to make sure I'm not leaking memory right now, but if I could instead store in a Map<string, weakref>, it'd be much easier, things could go out of ref and I could deal with that.
The single most important feature I'd like to see in JS are types. Typescript seems nice but I don't want to need a transpiler, especially since I'm doing a lot of live-coding in JS and compilation/transpilation times >50ms are already too much.<p>Other than that, JS could benefit tremendously from a more complete standard library, and a build system, including a file watcher, that doesn't rely on 200 nonsensical dependencies.
If Apple is indeed granted the patent on Swift's optional chaining (as was recently posted <a href="https://forums.swift.org/t/apple-is-indeed-patenting-swift-features/19779" rel="nofollow">https://forums.swift.org/t/apple-is-indeed-patenting-swift-f...</a> ), we wouldn't see this in future Javascript, would we?
As someome who has spent the last year primarily with Elixir, it is impossible to overstate how nice pipeline |> is.<p>It is one of the most convenient and readable pieces of syntax, and one of the primary reasons I pause before using javascript instead of Elixir in a given moment.
The biggest thing that is missing in my experience is finalizers or context blocks. I need some way to free resources allocated inside emscripten. Either python style context managers or go style defer or c++ style destructors on scopes would be a god send.
Some things I wanted in JavaScript is a goto command, and macros. They mention objects to compare by value, and I had a bit different idea which is a UserPrimitive function which has a similar meaning (but different; user primitives would also allow some degree (but still restricted in some ways) of operator overloading).<p>Bigint is a good thing they added. Sometimes you need to deal with 64-bit integers, and other times you might want unlimited range, so that helps. However, some operations that are not currently built-in perhaps should be in order to be more efficient, such as log2 of bigint numbers or counting trailing bits.<p>A built-in RegExp.quote() function is another thing (although it is easy to make, it seem to me it is something that ought to be built-in).<p>If macros are implemented, then many features can be done by macros and do not need to be built-in features.<p>One feature of JavaScript that I dislike is automatic semicolons.<p>And yet, many proposals (including these) may be rejected if better ways are found.
The only thing I absolutely hate is the import-as bullshit inspired by Python. I was told this was to assist static analyzers, but when you compare it to destructuring syntax you just get annoyed by the duplication.<p>+1 for pipeline operator
+1 for a destructuring switch
I like JS, I like the new features since es5, although I liked es5 also, I notice that the updates are now yearly it seems, which is mostly good since there was maybe a long delay in the past, but can be bad if there become too many features.
Coroutines (unlike async/await) would allow one to wait on an async result without losing the stack which is waiting. This would avoid the need for (often) inscrutable callback state machines (Javascript's version of GOTOS).
Not having to install the shit show of conflicting dependencies. Get a formal package manager instead of the twenty different ones. Basically take a look at python and realize the js ecosystem could actually have nice things.
Save navigation and equals/hashCode (as protocol, not using that ValueType thingy) are fine and definitely useful, but otherwise we should avoid adding even more syntax elements to JS.
I would love some of the syntactic sugar from Swift. Swift's `guard` and `if let`, along with the nil coalescing mentioned in another comment make Swift a joy to write.
I know this is a really contentious idea but I'd like javascript and typescript to merge into the same language. Type safety is the huge 800lb gorrilla in the room.
> Comparing objects by value<p>A handy helper I use all the time for this:<p><pre><code> export const jsonEqual = (a, b) =>
JSON.stringify(inspect(a)) === JSON.stringify(inspect(b))</code></pre>
I would like optional typing for the few places where it would be very useful. But people would enforce all types way too much, so I'm kind of on the fence.
Please stop adding new syntax, it only makes the language uglier. Instead of a special syntax for comparing objects, just add a function to Object.prototype.
Python writes to <i>local</i> files using native function <i>open</i>. Javascript has no native function. Because...?<p>We can open a window, write arbitrary text to it, use the browswer to 'Save as...'. Close but no cigar.<p>I'd like to use JS for a lot more than the web. MS Basic wrote user-entered text to a file 40 years ago.
Needs more punctuation. I don’t know about the rest of y’all but I get disappointed when I look at JavaScript and it’s not awash in a sea of angle brackets.<p>But seriously, be careful not to ruin it with too much “I need this!”
I was scrolling through this and I was like, where is optional chaining? Then when he gets to it, he's a bit against it because it's easy to write bad code. What? People still do nested checks like this all the time! It's not changing anything beyond making them more readable and I think more obvious when you think something might not exist (e.g. `some.very?.nested?.property` vs `some.very.nested?.property`). Sometimes it's not so much the nesting that makes it unreadable either, but that you're checking multiple objects, imagine writing `some.nested?.property && other.nested?.property`.<p>It's like saying promises shouldn't have been added because you can still write bad code with them and create nested promise hells ( I sure did when I first learned them). Isn't it better to say, no, best practice is to add ? only where you actually need them. The solutions he cites are not really solutions, they're just abstracting the problem away which most of as already do, but then the abstraction becomes hard to read because those checks have to be somewhere.<p>Worse I think is the comparing objects by value idea. I think it would be way too easy for beginners to reach for that solution. There are often better work arounds, it's quite rare imo to need to do a deep nested check of two objects that could be very different (i.e. contain different properties). Plus it's not like using a helper function is that verbose and a custom one can be really fast (if both objects contain the same properties, creating a function that "manually" checks for them all is blazing fast), same thing with deep clones.<p>Things I would really like, from most to least: optional chaining obviously, realms, pipeline operator, optional type checking, and enums (you can sort of fake them though, hence why they're last)