ECMAScript 2018: final feature set
2ality.com
2ality.com
If the result of parsing contains a GroupName, reparse with the goal symbol Pattern[~U, +N] and use this result instead.
But "the result of parsing" by definition cannot contain a GroupName because GroupName is not part of the initial grammar.
Furthermore it appears that the named capture group backreference syntax `\k<groupname>` is in fact valid under the "old" (no-named-capture-group) syntax. Thus the interpretation of `\k<groupname>` depends on the future parts of the expression, similarly to how `\3` can be an octal escape or a backreference depending on the rest of the expression.
JS regexp parsing is already underspecified [1] and requires two passes to disambiguate backreferences from octal escapes. Now it appears we potentially need a third pass to disambiguate named capture groups.
[1]: https://blogs.msdn.microsoft.com/ie/2010/08/25/chakra-intero...
* Asnyc Iteration: Looping over async lists, e.g, reading lines from file or an async generator.
Allows code like:
for await (const x of asyncIterable) { foo(x) }
* Spread/Rest (`...`): Makes FP easier. const a = { foo: 1 }
const b = { bar: false, ...a }
// b is { bar: false, foo: 1 }
Works on arrays (spread operator for literals) or objects (rest operator for destructuring)* RegEx features like named capture groups
* `Promise.prototype.finally()` - Callback function is always executed, regardless of what promise returns.
Maybe this is meta, but I wonder what it means for us in this ecosystem. Some of us have totally lost touch with whether the language features we use are supported by the runtime, or are even "canon". Right now I'm probably using a bunch of language features in different projects that are still proposals. I have a few handwoven .babelrc's in different projects that use all manner of things.
I'm almost 40 now and looking back on my programming career, what we do with JS and language features is truly bizarre.
It's even more problematic because some influential figures in the community push those non-standard features and encourage people to use them. Some are pretty harmless (object spread back when it wasn't standard), some are PROBABLY okay (class field declaration, pushed very hard in the React community because the ES6 class syntax with React kind of suck without it and they pushed THAT too early).
Some, however, are downright dangerous, such as decorators (pushed pretty hard in the MobX world) or bind operator (used to be pushed in the RxJS community, though not as much lately with pipeable operators). Those things are not standard, and in the case of decorators, the version being pushed doesn't even match the latest proposal. These are the stuff of tech debt nightmare when used at scale. Yet most people using them have no idea what kind of hole they're digging themselves into, and it's hard to blame them. Can't really keep track of all of that when you have deadlines to meet.
This is one of the main reasons why I am increasingly interested in TypeScript: it gives you more features than JS, but in a way that is consistent and manageable between projects.
It seems inevitable at this point that any large project is effectively going to be using a particular flavour of JS, with language or library extensions.
But I bet I'm missing something important. Rx is pretty huge and it looks like this feature isn't really. Does anyone know more, from the trenches? What are the downsides? Does Babel compile it well? Are all important use cases covered?
They work great together, using each's strengths to specific needs in an application.
Additionally, a lot of the weight of Rx is its large set of "higher order functions" beyond the basics of map/filter/reduce. Similar higher order functions are possible for async iterators. One such library for that is Ix, maintained by some overlap with the Rx team, and maintaining some consistency in operator names and APIs.
I've been using Async Iterables fairly heavily lately in an application in combination with Rx-like Observables (using the xstream library, rather than Rx) and Ix operators. I've been letting Typescript do all the downlevel compilation, and have been pretty happy with it in the use cases where I've been using it.
I mean, ever since JS got generators, it has support for unlimited length iterables. Isn't an unlimited iterable of promises precisely what you describe as a push stream?
I didn't dive deep, but I do believe I was able to cook up a generator function that produces an async iterable of mouse events. It was able to `for await` it and console log the event data.
Async Iterators/Generators are seen as "pull" because your "main thread" has to actively consume it (you `for await` results), whereas with Rx Stream/Observables your "main thread" passively subscribes to updates.
It probably still seems like a semantic distinction at that, especially as you can relatively easily convert between them. However, a lot of the big differences come down to how each technology deals with A) pressure (lots of items/events), and B) scheduling "intermediate" work (iterables do more work on the "main thread"; streams/observables are better at/have more tools for chunking work on a scheduler/thread pool outside of the "main thread").
Which is also why JS isn't exactly the best language to discuss the differences between async iterators and streams/iterables, because a lot of those biggest differences/distinctions aren't very important in mostly-single-threaded browser JS, which is its most common problem domain.
I worry that spread operators make code less readable. You really have to squint and think more when confronted with one.
They also make your code less understandable to a beginner, or people coming from other languages.
One of my favorite ways to use them:
const foo = {};
if (bar) {
foo.bar = bar;
}
Turns into: const foo = {
...bar && {bar},
}; const foo = {
...(bar && {bar}),
}; const foo = bar ? {bar} : {};
be both more efficient and more readable? const obj = {
foo: 1,
bar: 2
};
const propToDelete = "foo";
{ [propToDelete]: _, ...newObj } = obj;
newObj; // { bar: 2 }
but will probably be more performant than `delete` in the long run.if you really want to write shorter code, try
const foo = {};
foo.bar = bar ||undefined;
I don't even care that it isn't backwards compatible. Eventually platforms will catch up... so the sooner it's added the sooner everything will catch up.
1. Datetime
2. Expand the encoding to escape '<' and '>'
Being able to specify a datetime as local vs utc would also be nice... so "2018/01/31 17:35:21.2222Z" for UTC and "2018/01/31 17:35:21.2222" for local.
As to the actual format used... that it's just a bikeshed argument waiting to happen. I picked y/m/d for no particular reason (well... other than my ancient preference for a simple sort key). I also picked 24 hour time for no particular reason (well... other than my ancient preference for a simple sort key).
No one would really care too much one way or another what the format was (so long as it was easy to generate using common server side technologies... node, php, java, .net).
I also don't consider a website serving machine-generated javascript to be a "compiled application" analagous to a C, Flash or Java binary (whereas WASM would be,) but almost every time I try to go down the "javascript is not machine code or bytecode" rabbithole, I get downvoted to oblivion.
The majority of news, social media, video, media sites, message boards, online games and web apps fit this description. I'd wager that 95%+ of websites produced by a paid professional today are in this category. Unfortunately no, I don't have data to back this up, only my perception as a web developer.
[1] due to relying on a module system, es6 transpiler, etc
First off I must be careful and acknowledge that a language which changes at a pace faster than the body of programmers using it can safely absorb could be considered an anti-pattern. As it stands I'm not sure if JS fits this.
Look at how Java has changed over the years. Back when it was created the syntax was appreciated by many as resembling C++ enough and being OO enough to be "good". Obviously there were many nits to pick by purists but programmers adopted the language and many people touted it. Java did not become popular because non-technical people were pushing it. Programmers liked it well enough.
I was a religious zealot when it came to OO. Now I find myself loathing large OO systems and trying to write procedural functional code as often as possible and only using classes when necessary. The Java language has evolved to add lambdas, streams, etc.. Should Java have added lambdas or should it have stayed the way it was, "good enough"? Even if one is a programming paradigm zealot of any persuasion one must acknowledge that a great deal of production code was written just fine using only the early Java language features. Should we have stopped there?
If code should be written first and foremost for programmers to understand and only incidentally for compilers to then it should stand to reason: as our collective understanding of how to express the behavior of a computer program evolves, so should the language(s).
Why would WASM mean slowing down JS changes?
It seems very improbable to me that this will occur in the next five years.
As for the pace of changes, it's hard to tell. All the same, if TIOBE is to be believed, JS is getting more popular, not less.
1. The language design is flawed. That is, the desired functionality requires changes to the core language, because it can't be made from existing building blocks. The fundamental language constructs are not universal enough, so new functionality will always require "just one more" special case in the language itself.
or
2. People are shoving things into the core language, that should rather be implemented as a library/framework.
I think JavaScript’s core foundation is changing because its use cases have rapidly changed. Like C++ or PHP though, it likely has a lot of legacy cruft.
Are any Ruby experts able to chime in if its language/runtime changed much after Rails hit the scene?
Keep adding rules and break the compatibility of strict code, or forget about it and live with current problems forever?
What things going into core do you think should be a separate framework?
But a flawed language cannot be made non-flawed while keeping backwards compatibility... E.g. JS has now two different ways to write functions, with slightly different semantics.
>What things going into core do you think should be a separate framework?
An example would be async/await and generators, both which are just a special cases of coroutines. If JS would have coroutines, then these two would just be coroutine libraries.
Sure it can. Just introduce new syntax and discourage use of old syntax, ideally with tooling. For example, `var` is disallowed by any popular lint config, and for most practical purposes, it doesn't exist in JS anymore. The execution environment will still handle it, but it's not an available option when writing code in any professional or non-professional project I work on (because it won't pass lint).
Plenty of languages do this: Java raw types, Python old-style classes, goto in lots of languages. Python actually did a breaking change to remove old features, and it's a good example of how breaking changes can cause much more trouble than you might expect.
That is surprising to me. I work with code that is more than a couple years old all the time and I would guess most people do to.
Just 2? More like 9:
* function expression
* function declaration
* arrow function (single line, single param)
* arrow function (single line, multiparam)
* arrow function (multiline, single param)
* arrow function (multiline, multiparam)
* object shorthand
* class declaration
* class expression
async/await could be implemented with just generators, and were so implemented in ES6; async/await was added to the language because it was convenient. A language without full coroutines is fine.
Websites evolve, and that's the choice of developers around the world. You have no right to complain if you don't keep your software up to date to a reasonable level.
If you want to use 4 years old software, you MUST accept things are broken and that it's your fault. Try downloading Firefox 1-10 and see if they work today ;)
But if everything operated like the web ecosystem, we might consume 100% of our time and money just on upgrades.
And it pretty much guarantees there will only be a handful of vendors, because it's very expensive to stay current.
All other things being equal, a decade is preferable because time/attention is valuable. Frequent and in particularly non-careful updates can put individuals and in the grip of a form of the red queen problem rather than being able to spend time/attention on new levels of capability.
I don't particularly mind some obsolescing of browsers where JS is concerned, and browsers in general have done a remarkable job of retaining backward compatibility.
More problematic, though, is the attitude that's more or less every website should be a JS-powered (or, in the future, web-assembly) SPA without any kind of back-end fallback for user agents that don't support it, thus making JS capability the bar for any UA. That's short-sighted, doesn't consider user conditions outside of a narrow range of experience, doesn't consider that there might be user agents other than browsers as commonly understood. If that's all you have the resources to do and how you choose to spend them, that can still be reasonable engineering (though my experience is the benefits of figuring out how to make it work w/o JS first -- if it's possible -- often pays engineering dividends), but I think it's weird it's the default now.
> Try downloading Firefox 1-10 and see if they work today ;)
Firefox 1-10 would be broken because they're embedded in a set of assumptions about specific non-web platforms, not because many (if not most) websites couldn't reasonably support them as clients. I don't see any reason to import the shortcomings of non-web platforms into the web.
So thanks, but no thanks. There is enough of planned obsolescence already, no need to add another weapon to the arsenal.
Babel can already translate ES2018 async iterators and rest/spread into ES5 code that works pretty much everywhere.
> Why stop adding new useful features?
No actively used languages that I know of have stopped adding features.
RegExp Lookbehind Assertions
Finally... I've had to lookaround it's absence too many times.https://github.com/tc39/set-methods https://github.com/tc39/collection-methods
Call me stupid, when I'll get whiteboard tested on these shiny new concepts, but I really don't (and you shouldn't also) give a rats ass about all of this.