Hacker News new | comments | ask | show | jobs | submit login
What's New in JavaScript for 2019 (okta.com)
58 points by reverentgeek 25 days ago | hide | past | web | favorite | 79 comments

I might get heat for this but personally I find the JavaScript ecosystem to be a mess. There are so many changes to the language that are done aggressively which I think are done without much thought. For example, the promises API, now we also have async/await. The module system, with require(s), then import/export, and there's browser JS and system JS (node), and npm and now yarn, then your build system, with webpacker, browserify, bower. Oh! You might also be interested in using new JavaScript syntax so don't forget to use babel.

And the funny thing is they are teaching all these at bootcamps and the students have a hard time trying to understand the concepts with so many variations in them.

There is however light at the end of the tunnel which I think where TypeScript is.

> I might get heat for this but...

Some variant of this is the top-voted comment of every HN thread on modern JavaScript.

> For example, the promises API, now we also have async/await. The module system, with require(s), then import/export, and there's browser JS and system JS (node), and npm and now yarn, then your build system, with webpacker, browserify, bower.

Async/Await are essentially sugar on top of Promises -- use them if you want, you don't have to. Require has been deprecated in favor of import/export to be more semantically meaningfull (e.g. with TypeScript). Webpack is the next iteration of the Browserify approach, and Bower is just flat out dead.

All of this happened 3-4 years ago, if it's your job it's not hard to keep up. If it isn't your job there's plenty of guides out there to get you up to speed. I wouldn't expect to be able to jump back into Android dev after 5+ years away from it without doing some reading, I don't know why people expect web development to be so static.

My guess is there are too many options, and ways, to the casual person it’s a lot to learn/compare then choose, for people that don’t care to compare well there is always a bootstrap starter app

> All of this happened 3-4 years ago, if it's your job it's not hard to keep up. If it isn't your job there's plenty of guides out there to get you up to speed. I wouldn't expect to be able to jump back into Android dev after 5+ years away from it without doing some reading, I don't know why people expect web development to be so static.

The thing is that the JavaScript language is so aggressively changed, unlike Ruby for example, that for years, working with it professionally, the only change I can remember that was significant in my work was the safe navigation operator `&.`. The build tool (Bundler) is still the same, along with other tools. Not sure why JavaScript can't do the same? More innovation I guess?

After the big dump of new features in ES2015, I don't find the pace of planned updates to the language aggressive at all. JavaScript is still playing catch up.

People will complain if they don't add features. When they do add new features, people complain that they're "bloating" the language or moving too fast. Damned if you do, damned if you don't.

The JS ecosystem is a different matter.

You can use the old JavaScript if you want to. All those fancy tools just compile down to the same old es5 you can write by hand if you're so inclined.

> Not sure why JavaScript can't do the same?

We should be celebrating the fact that JavaScript finally has a sane module system after 20+ years, not complaining about it. Ruby had namespaces and modules from day one.

It's really not though. If you look at the official yearly releases, you'll find that there have only been a few major changes since ES5 (aka ES2009): Async/await, modules (import/export), arrow functions and destructuring.

None of those are mandatory. They're mostly just syntactic sugar on top of existing features.

Every other change has just been things like new util methods on primitives like the string trim functions.

The build tools are separate, don't conflate them with the language. That being said, for ~4 years, most people's build chain hasn't changed; webpack with a babel plugin.

The problem is that JavaScript wasn't considered a stable and useful language until it really started to hit its stride in about 2009. So all of the changes that have happened are because the community is still figuring out the best way to do builds whilst things in the language are still changing.

Ryan Dahl seemed to imply that promises were a necessary pre-requisite for async/await. https://medium.com/@imior/10-things-i-regret-about-node-js-r...

I don't have the actual transcript so summarizing based off of someone else's comments:

* I added promises to Node in June 2009 but foolishly removed them in February 2010. * Promises are the necessary abstraction for async/await. * It's possible unified usage of promises in Node would have sped the delivery of the eventual standardization and async/await. * Today Node's many async APIs are aging badly due to this.

Async/await is just syntactic sugar in languages. It's always implemented by some kind of promise/futures/task based API, itself usually built on some kind of state-machine/iterator/generator model.

Promises could be shimmed in browser JS (Jquery was my first experience with it) where async/await needed something like a babel/webpack transpiler for the syntax to really be feasible in a browser.

It's becoming the new PHP, where "classes" are an after-thought and there's a beginning of a "frankenstein's monster" of features pulled from other languages.

Having said that, looking at the code sample it's looking quite nice (ignoring the #'s).

Isn't TypeScript committed to implementing all stable ECMAScript features?

It being a superset with TypeScript-only features on top of ECMAScript, wouldn't the "aggressive changes" you complain about be worse?

It’s fine if you are a fairly experienced JavaScript developer, and understand the tools that you used to have, and what their pain points were, and what solutions are coming along the way; then you just go with the flow and enjoy the progress.

I can understand the frustration of people who don’t touch JavaScript on a daily basis, or confusion of newcomers. I can sympathize. But I don’t think that personal inexperience should reflect negatively on the language.

I certainly get framework fatigue with JavaScript but I think most of that has little to do with the core standard. The things that the core language has added I have found, for the most part, to have been well-considered and beneficial.

Async/await and promises do seem to be a thorough solution, with my main criticism being that they are difficult to conceptualize what is going on when a lot of promises are being composed together.

I love TypeScript but I think it's funny that your answer to the woes of JS complexity is just another JS transpiler. It's a tool you're familiar with and one that you like so you give it a pass on all the complaints you leveled up front. Maybe... just maybe... in a similar vein to TypeScript, most of these other JS tools were built to solve real problems and not just to deliberately confuse you.

All of these bits and pieces were built for good reason, it's nice to see them grow organically in different directions but able to borrow concepts from each other or collapsing down (as happened with Node and IOjs).

As a beginner it's a far more daunting picture, compared to Rails for example, but as a practitioner I'd like to build my project with pieces suited for purpose.

I hadnt used es6 syntax in 5 months and just got the ‘luxury’ of discovering that babel 7 came out sometime and that all of the babel dependencies are namespaced and renamed, but are the new best practices “or else”

Basically everything on stackoverflow/github issues/random JS blog is outdated regarding the inevitable error messages youll google

I don't disagree that it's moving fast, but my experience is that the thriving ecosystem makes JS apps nice to work on.

Every project has its own little tech stack, each part being filled a-la-carte by some JS framework/library/preprocessor. The server might use express or raw node or Koa, the web client might use React or Angular, styles might be done with SCSS or styled-components, etc. JavaScript might have a different syntax between projects if they're using typescript/babel. There are lots of choices to fit many needs and preferences, and that's a good thing™.

All of these technologies are built around the same language and syntax, which at its core is relatively simple to learn (aside from the occasional type coercion/prototypal inheritance weirdness). This makes learning new frameworks and tooling easy: does it need a config file? Chances are it's a raw .js or .json file with a similar format to webpack.config.js or package.json or .eslintrc.

It's not a huge ask, nor would it be terribly difficult, for one developer to become competent with both Angular and React, for example. And once you've made your choices for your project and installed all the npm packages you need, there's no need to keep all of them updated to the very latest, bleeding-edge releases at all times. Just install patch (0.0.x) updates and wait for npm to warn you about any security issues in your existing packages.

That's why I'm kind of surprised to see so many companies advertising JS jobs with requirements like "Must have 3 years experience with React." Any competent Angular developer should be able to pick up React and start being useful in a matter of weeks, not months or years. Just hire JavaScript Developers, IMO.

> For example, the promises API, now we also have async/await.

These go together, right? An async function returns a Promise, await operates on a Promise.

You can sill use the "good parts" but you will probably be accused for being unfashionable.

if we’re here, i’ve got a rant about npm. if you have more than a few dependencies, you need to download half of the internet for all the required 3rd party packages. this has security implications too, as i see no way to be able to watch them all, even with a local mirror

@downvoters: do you care to add a reply? it’s silly that instead of having a conversation, we’re doing this.

I didn't downvote you but I think you're getting grayed out because it's a tired argument that's been had time and time again. It's just… kinda pointless to have it again.

Yes, the all-too-common super-deep dependency trees are a problem. If you're reasonable about your dependencies though it doesn't happen (my last few JS dependency graphs are pretty similar to my Python ones).

One of the issues is the stdlib and the other issue is a different mindset due to a lower barrier of entry to creating a package. (eg. creating and maintaining a package in Python sucks, so you're less likely to do it for small, self-contained things rather than create a utils.py)

shrugs, I honestly don't know what meaningful change this discussion can lead to. People are generally aware of this, and the problem isn't actively getting worse, so I imagine it'll get better over time.

ok, that’s fair, thanks. i haven’t participted that much in js related discutions, it’s just frustrating to me and didn’t know that this is pushing some hot buttons :)

I tend to agree with the article author about the use of a # (or indeed any punctuation mark) for private fields. I think it is just a personal preference thing though. Is there any publicly available discussion that shows what lead to this decision?

If fields in class definitions are incorporated I would like it to simultaneously make the field names in scope for any methods within the class definition.

  class Fish extends Vertebrate {
    color = "blue";
    constructor (speed) {
      this.speed = speed;  
      if (speed > 5) color = "red" // does not need this.color because color is a class field.

  Fish.prototype.setColor = function (newValue) {
     this.color = newValue;  // this. is required because this function is outside the class definition.
Adding this feature would allow for much tidier method bodies since there is now enough information to imply this.fieldName from fieldName alone.

Ok reading that I'm going to amend my suggestion above.

    class fish {
     color = "blue";     // color is now a name in scope for this class definition
     #agenda = "Total World Domination"  // agenda is now a name in scope for this class definition

     reveal () {
       console.log("I am a " 
               + color + " Fish "  // interpreted as this.color
               +"seeking " + agenda // interpreted as this.#agenda;

You can still have this.agenda for public addon fields. But for the private one you can refer to it within the class definition without either this. or #

Yes please make the syntax simple like this! Even cleaner:

  class fish {
     color = "blue";    
     private agenda = "World Peace"  
           agenda="Secret World Domination"
     reveal () {
       console.log(`I am a ${color} Fish seeking ${agenda}`)

At this point why not just have browsers run TypeScript natively? Remember the <script type="text/javascript"></script>, maybe just put <script type="text/typescript"></script> and be done with it.

Because it's a slippery slope that you can never get agreement on (even majority agreement on, let alone overwhelming agreement). Why TypeScript? Why not Flow, or even Python or ClojureScript, or (my vote...) PureScript?

Then what happens in 2 years when the "next big thing" comes out that is mind-boggling-ly awesome and obviously obsoletes TypeScript? The latest addition to JavaScript is Array.flat... it should be called Array.flatten, but there was a popular third-party library 15 years ago that used it and you can't go breaking the web every time there's a new "best way" to do things.

Each fan of each language will happily tell you why theirs is better than any others, and why it's the obvious choice to be the default in a browser. Everyone might agree they don't want JavaScript, but no one will ever agree on what should replace it. That's why your two options will only ever be "JavaScript" or "transformed/WebAssembly-fied other language".

Good example, imho better to stop adding stuff to JS, declare it legacy and leave support in browsers so old pages render fine. Then add a new language without compromises like `flat` or `includes`.

What's the point? If you're going to use typescript, you will want to do typechecking. And if you do typechecking, you might as well compile your project properly.

I'd honestly rather have browser support less than more and I'm happy with type annotations remaining a language superset. The current typescript situation is actually fantastic and as a python dev, I envy it a lot.

If TS becomes the majority, it seems to me like the browser debuggers could start using types at run time to catch some interesting things that aren't so obvious when compiling the pieces. I.e. help the people who add the final touches to a site check that they have not messed it all up without the project writer needing to decide how many guards to compile in to the project interfaces.

Probably the largest problem I have with modern projects is how unfriendly they are to experiment with on the page, even if there's no intention to prevent it.

Hmm, I can't quite see what kind of thing browsers could catch that typescript itself couldn't, since the whole point of types is to be useful at compile-time.

That said I could see some type introspection being useful in the devtools. This is probably already feasible though, as devtools are sourcemap aware. And typescript is written in typescript after all, so it couldn't be that hard to pull in support for it in the devtools, could it? :)

Cool idea!

In my uneducated opinion, I think this is the direction things will go. Typescript will steadily supplant JavaScript and browsers will eventually roll out native support for it, and JS will be relegated to a legacy language.

>Typescript will steadily supplant JavaScript and browsers will eventually roll out native support for it, and JS will be relegated to a legacy language.

Typescript can't supplant javascript or relegate it to a legacy language... because typescript doesn't compile to bytecode or machine language, but to javascript. Browsers that support typescript natively must by definition also support javascript natively, and the more of the former you have, the more of the latter you have.

And C++ used to compile to C at first, I don't see your point.

Having TypeScript support in the browser doesn't make sense as the idea behind TypeScript is to add a compilation step so that type errors can be caught at compilation time. eg. before the code runs.

The browser still has to parse the JS code before executing it. It will complain if you get the syntax wrong, type checking is the same thing.

> There are a number of proposed changes to Classes, including field declarations, private methods and fields, and static methods and fields.

So make it look full on like traditional OOP with classes, I guess? I suppose the prototype folks lost this debate.

It is interesting there is so much push towards classes now when a big part of the ecosystem (react) is moving away from them with react hooks.

I don’t really like the direction at all. What’s next, templates? Don’t understand who is really pushing for this.

Did you look at the proposal ? Declaration #name prefixed with hashtag. I really hope that won’t go thru.

    #this_is_not_a_comment = 6;

Yeah... it's ugly as heck but they're clearly trying to avoid new keywords. I hope the TypeScript folks can convince ECMA to adopt normal keywords like they use:


It's not just about keywords, it's about shadowing mostly [1].

For example, what does `this.foo` access in an object? the private property `foo`? the public property `foo`? What about if I'm using your object and put a new property `foo` on it after it's created, then what happens?

None of the answers to those questions are really good. If the private shadows the public, then how do you access the public? If it's the other way around, then external users can break your private fields by adding a public of the same name, which kind of defeats the purpose...

TypeScript can get away with it because it's not really enforced by the runtime, only the typechecker, so their `private` isn't really private outside of TypeScript.

[1] https://github.com/tc39/proposal-class-fields/blob/master/PR...

I've read the TC39 proposal and I still don't understand what's wrong with "private".

You can have a public field named the same as a private field and all fields in JS are accessed by "this.fieldname" so you need a way to access the private field differently.

This one was weird but for someone who only does Javascript it might not. # is not a comment in Javascript but is in many other languages I use which really threw me for a loop.

It looks odd, but the pound sign isn't a comment character in JS, so ... I guess it's like @ for Ruby.

The only thing that still blows my mind are the private fields and methods. I understand there has been plenty of debate about it, but have not followed the conversation. I really hope that syntax does not get finalized.

Yes. I've read some of the reasoning behind choosing the syntax. Regardless of the issues, I think going with the current proposed syntax is a terrible mistake.

Me too, in fact it is the only thing I dislike about the upcoming language features.

Yes, absolutely alien/awful syntax. `private` is already reserved word, why not use it? It has been reserved word for this specific moment when it's needed for exactly this, am I wrong? What's the point in having reserved words in spec if the spec is afraid of using them? I don't get it, can someone explain why this ungodly # made it so far already?

`flat` and `flatMap` are highly welcome additions for me; concatenating a bunch of lists together has historically been a very common operation for me, that right now is done best as

It is also the basis more generally for the list monad, where `.flat()` is the `join` operation and `.flatMap()` is the equivalent `bind` operation.

So, like, the simplest example is if you're just getting a bunch of results from a paginated source -- you want to flatten them, and it is really nice to just have a method for that.

The list monad case is more interesting because it gives a syntax for list comprehensions:

    [ x + y for x in list1 for y in list2 if x % 2 == 0 and y % 2 == 1 ]

    list1.flatMap(x =>
      x % 2 !== 0 ? [] : list2.flatMap(y => (y % 2 == 0 ? [] : x + y))
And more theoretically this list monad is all about composing nondeterminism, where one input could produce any of N outputs: if you store all of the current possibilities as an array then flatMap is the core composition primitive.

I'm _super_ excited for flat and flatMap. In working with multidimensional arrays, I'm always needing to use my own `flatten` function before returning my value. I love that this is getting native support.

JS the language is great, and it becomes even better with TypeScript. But the ecosystem leaves a lot to be desired.

Having become proficient with Node/Express/Sequelize at Fullstack Academy and then used them for several months, I really miss Django and Django REST Framework. The ORM, serializers, effortless filtering and permissions, etc. are--with all due respect--simply unmatched in JS-Land.

As for the front-end, I learned and used Ember for over a year before picking up React (it was "cooler" and there were more jobs). So many decisions I've agonized over with React/Redux were solved years ago with Ember. But the problem with Ember is its proprietary object system and its lack of momentum.

If I have a choice, I will be starting new projects with Django on the server-side, and Ember only when an SPA is necessary. In the past, I hesitated to use Django for templates, but the lack of a robust client-side ORM has made that option more attractive.

> Why not use private.x to refer to a private field of this, and private(that).x to refer to a private field of another object?

I don't find the answer to this [1] to be particularly compelling. This actually seems like the right solution to me.

[1] https://github.com/tc39/proposal-class-fields/blob/master/PR...

Followed the links of the article a bit. The document explaining the process of finding a good name ("globalThis") for global is pretty cool: https://github.com/tc39/proposal-global/blob/master/NAMING.m...

Yet another signal that ClojureScript was ahead of its time when it was created.

If you want to make programming inaccessible to newcomers, start making special characters that inexplicably mean special things... like # means 'private' when placed in front of a function.

That is a legitimate concern. Even if the person isn't new to programming and is coming from other C-like languages such as Java or C#, there's a good deal of precedence. Just like the "Don't Make Me Think" usability argument, we ought to stick with the conventions that people already know and are familiar with.

The proposed globalThis seems like a hacky solution to a bad problem

I agree. It's ugly. I understand it's named globalThis to avoid collision with other libraries and breaking things, but my goodness.

so static is `static` but private is `#` ?

I wonder whats the reasonig behind it? `private` is already a reserved word in JS, why not just use it? https://www.w3schools.com/js/js_reserved.asp

I feel like i'm spamming this link every time the private fields stuff comes up, but take a look at the FAQ, it explains the reasoning behind it and why they didn't go with alternate options (like underscore, private, or others).

I was against it at first, but after reading through that document, i'm on their side now. It'll be a small but useful addition in some situations, and it's scope is extremely limited.


Thank you for that link, will read it carefully. From the first glance it feels like an attempt to cover mess with a bigger mess:

> this is already a source of enough confusion in JS; we'd prefer not to make it worse

> Property access semantics are already complicated, and we don't want to slow down every property access just to add this feature.

> [private x] in JavaScript this would silently create or access a public field

Pardon me, but # as a declaration method of privates is an abomination.

Yeah I have to agree with this. I'm getting this vibe from a lot of changes to JS lately. A mess designed to cover another mess and people almost blindly supporting the new mess just because there is some logical rationale for it.

There have been intense debates already for this decision. The fundamental reason is because Javascript has a messy "this.fieldname" requirement to access public fields so the only way to use a private field requires a symbol to denote that its private and not overlapping.

I would've preferred the "this.private.fieldname" instead but # is what ended up winning.

Noob question: What does static mean in other languages? Is it basically Foo.prototype.bar !?

A static property is generally a global variable namespaced to the class, so Foo.bar.

Huh... why would there need to be something new for JavaScript in 2019?

At this point, it looks like they might as well import the Java syntax and call it "JavaScript fusion" and be done with it.



Not the OP, but so much about javascript rubs me the wrong way.

1) Mandatory javascript is making the internet a hostile place. Basically every site you visit asks you to run untrusted code to view it now. What could possibly go wrong?

2) It's a hastily thrown together language that was rushed out the door by a Netscape engineer long ago, and it shows.

3) The 'ecosystem' is like swamp right now, at least to me. Frameworks and approaches change almost monthly. To me the whole thing looks like totally unstable set of immature code that I'd hesitate to build on.

> Basically every site you visit asks you to run untrusted code to view it now.

Javascript didn't do that. The needs for ads and analytics are doing that. You know what people used before Javascript? Flash and Java. You want untrusted code running on your system, you're going to get very much untrusted code running on your system.

The current situation is a huge improvement over that. No, Javascript isn't making the internet hostile; it's making it useful. Unfortunately, ads are making the internet hostile … but they're also making it profitable, thus… useful. YMMV. People are working on alternatives, it's not an easy problem to solve.

> It's a hastily thrown together language that was rushed out the door by a Netscape engineer long ago, and it shows.

Ok, we're beyond that now. Would the web be better had we had Lua from the get go? Maybe. It'd also be 1-indexed. Would it be better had we had Python? Well, we'd be stuck with shitty lambdas. You know, Javascript is an ok shell for a language that has received a lot of work since.

There is no programming language on earth that can compete with the amount of effort thrown into improving Javascript, ever since that "Netscape engineer rushed it out of the door".

> The 'ecosystem' is like swamp right now, at least to me

It's not. Again, 15 years of Python speaking here. Javascript's ecosystem is active, but the most popular frameworks and solutions are years old. Typescript is from 2012, React from 2013. Both have rock-solid APIs and backwards compatibility. Other popular frameworks also take this stuff very seriously. And the older "progressive enhancement oriented" frameworks such as jQuery are over a decade old and your 2007 code still most likely works with them.

The JS ecosystem is what you get when you lower the barrier of entry to an extreme. There's a lot of crap in it, but you're supposed to do your due-diligence with any dependency, not just in that one language. When I pull in a new library in Python, I look at its codebase first: Is it clean? Maintained? Tested? Popular? You should do the same with JS dependencies as well, you just get more choice; more chances for your problem to already be solved.

I'm alerted that javascript tends to bloat the stdlib. Most of the features mentioned can be implmented as a external library. This is benefitial for users as they can switch the implenmentation and upgrade versions without waiting for all of their users to upgrade the runtime first.

The prime example of javascript unnecessary bloat is fetch api which is mere wrapper for ajax calls, was developed a while ago but still cannot be used because of lack of support in older runtimes.

From a performance standpoint it’s way better to have stdlib grow as opposed to JS bundles. Modules aren’t shared within a page so you’d end up with a lot of duplicated code that the user would have to continuously download and parse.

The problem here you can only rely on stdlib when most of your users have runtimes with it. For the browser features, you may never live up to this.

Its worse to forever live with two implementations(native and polyfill) and as large bundles, double the troubleshooting effort and extra support.

I, on the other hand, am happy with this. It means not depending on a 3rd party (whose motivation or trustworthiness may fluctuate), it's easier to re-use code form other projects, and we don't have to worry about "what version of .each are we using?"

I do believe your concerns are still real ones, however. Fortunately, we can poly-fill.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact