Hacker News new | comments | show | ask | jobs | submit login
JavaScript for People Who Hate JavaScript (zachholman.com)
429 points by ingve 9 months ago | hide | past | web | favorite | 329 comments



Background: I learned Javascript 1997 and kept up.

I have extensive experience in ES6/React for the browser and Java/Kotlin for Server-, Desktop- and Mobile-Apps.

A week ago I switched a fairly new project from the usual setup (react/babel/webpack) to Kotlin-code only. My IDE compiles the Kotlin to JS now and webpack serves it as usual.

Writing the react-bindings took me an hour, after that my productivity went up by about 10.000%. It's finally on par with my productivity on server and desktop. No type errors, fast refactoring, no "undefined" errors and all the goodies (extensions) of Kotlin.

Removing the complex eslint settings and babel-setup from webpack and package.json felt triumphant.

My JSX looks like this now and is completely typesafe:

    val LieferungenList: (props: ListProps) -> ReactElement = {
        Datagrid {
            div {
                className = "..."
                ...        
            }
            TextField {
                source = "date"
            }
            TextField {
                source = "produktname"
            }
            EditButton {
            }
        }
    }
I even get compiler-errors when I nest HTML-tags the wrong way (h1 inside h1) or so.

I couldn't be happier. I'll never touch plain ES6 again.


What advantages does this have over Typescript? The ecosystem and mindshare are overwhelmingly in TS' favor I would imagine.

For compile-to-js languages it seems most attractive to those that use the host language (Clojure, Scala, Kotlin, Haskell, etc.), whereas for would be js expats, Typescript seems like the natural choice given current trends.

I think for a compile-to-js language (vs. a transpiler like Typescript) to take off it's going to need at least:

  Tiny generated binaries
  Great js interop
  Large ecosystem
  Seamless cross compilation (e.g. JVM/JS)
  Fast compiler
Reason + Bucklescript is the only combination I know of that could potentially pull off the above, blazing fast compilation and miniscule binaries being its greatest strengths at the moment.


Typescript still has some issues that only a "real" strongly typed language can fix. The biggest one is related to third party JS/TS libraries. If the object was 'any' at some point, if you make an invalid cast Typescript will trust you. If it's a union type, typically (Obj | undefined), everything will work fine until one day the object is undefined and everything blows up. You won't know because everywhere in your code the object can never be undefined.

Essentially Typescript Is too trusting. In Java or similar languages, if something comes in as Object you know all bets are off. If you cast and it succeeds you know 100% what kind of object it is. In Typescript it's possible for the type to look fine but be completely wrong, or worse, wrong in a subtle way. And there's no way to fix this without breaking interop with JavaScript.

Since Java has always been strongly typed and has a ton of libraries available this isn't an issue in Kotlin.

Java/Kotlin are just far better designed languages and no amount of banging on JS is going to make it as well designed. Look at PHP, after 10+ years of trying to make it reasonable it's only "okay", there's too much baggage.

The bytecode for Java/C# is much more compact than JS, the runtime is about 10x faster, they have far better standard libraries. They will compile down easily to wasm since their VM's essentially already compile down to native machine code on whatever platform they run on. It's as easy as adding a "wasm" machine target to their runtime and porting the garbage collectors.

I fully expect Wasm to wipe out front end development as we know it. Java and C# are far better suited for what the web has become, essentially an application platform. We've seen the future already, just 10 years too early, in Java applets.


> If the object was 'any' at some point, if you make an invalid cast Typescript will trust you.

I believe any language that supports "any" allows this. Doesn't Kotlin? https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/

> If it's a union type, typically (Obj | undefined), everything will work fine until one day the object is undefined and everything blows up.

Not if you set strict: true in your typescript options, or you can separately enable just strictNullChecks

> Essentially Typescript Is too trusting. In Java or similar languages, if something comes in as Object you know all bets are off. If you cast and it succeeds you know 100% what kind of object it is. In Typescript it's possible for the type to look fine but be completely wrong, or worse, wrong in a subtle way. And there's no way to fix this without breaking interop with JavaScript.

Instead of casts that fail, typically you would use type guards to deal with this. That way you can isolate unsafe casting code to a single place.

> Since Java has always been strongly typed and has a ton of libraries available this isn't an issue in Kotlin.

DefinitelyTyped (http://definitelytyped.org/) has types for over 3500 popular libraries: https://www.npmjs.com/~types

> the runtime is about 10x faster.

Hmm. I see 1.5x-6x here, with average around 3-4x: https://benchmarksgame.alioth.debian.org/u64q/compare.php?la...


> I believe any language that supports "any" allows this. Doesn't Kotlin? https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/

Kotlin's Any is pretty much the opposite of TypeScript's any. In TS it disables type checking completely (according to the docs). In Kotlin it's the top type (similar to Java's Object type), which anything conforms with, but doesn't expose any operations at all (except for the stuff that the JVM provides for free).

The closest match to TS' any would probably be C#'s dynamic https://docs.microsoft.com/en-us/dotnet/csharp/programming-g....


Actually, the Kotlin equivalent to TS' any is 'dynamic': https://kotlinlang.org/docs/tutorials/javascript/working-wit...

You can declare a `dynamic` Kotlin variable like this:

   val myObject: dynamic = null
The myObject above is not type-safe. It seems that the reason for its existence is interop with existing JavaScript code.

The Kotlin `Any` class is actaully more related to Java's `Object` class. (It's the superclass of every Kotlin class.)


Yes, this is the effective difference between Typescript and typecasting in most other languages. Typescript, since it compiled to js, doesn't know the runtime type so it can't use reflection to make sure casts are valid. It just takes your word for it. If the cast isn't always correct prepare for a world of pain trying to track it down instead of getting an exception on casting failure


I encountered this the other day, while playing with typescript for the first time. Is there a good solution, such as a utility function that does a runtime check before casting? I suppose I could write one for each type cast, but it seems like I shouldn't need to.


Yes, a runtime check in TypeScript is the same as a runtime check in JavaScript.

    function inc(n) {
      if (typeof n === 'number') { return n + 1 }
      throw new Error('Parameter n is not a number');
    }
If you wanted to actually runtime check all types (probably not advised) you could parse the type annotations.

Or you could define your types using something like JSON Schema and validate against that.

https://github.com/bcherny/json-schema-to-typescript

https://github.com/YousefED/typescript-json-schema


I'm sorry to say but... This check won't help with accidental incorrect casts. Typeof in typescript is a pass through for the JavaScript function, so it only returns what the JS version does.

A check for a string or number will work, but a check against a typescript object or something complex like a union type will just return 'Object'


You can use a tslint rule to block casts. That way you will only be able to use type guards to change the type of something.


Kind of maybe. See http://blog.wolksoftware.com/decorators-reflection-javascrip... for use of experimental reflection API.

Note that Typescript tries to follow JS to remain a superset that easily compiles down, and the metadata API is currently a stage II Ecma proposal so it's marked experimental.

It should be fairly easy to build a types casting method using that.


> Kotlin's Any is pretty much the opposite of TypeScript's any. In TS it disables type checking completely (according to the docs). In Kotlin it's the top type (similar to Java's Object type), which anything conforms with, but doesn't expose any operations at all (except for the stuff that the JVM provides for free).

If you want top-type like behavior in TS, you want to use `{}` instead of any, since the language is structural. Anything satisfies it, but it exposes no members without a cast or guard to a more specific type.


Fwiw, microbenchmarks are not a good indicator of application perf in general. That said, nodejs is pretty fast. Also a memory hog, and doesn't support parallelization.


I always have a chuckle when JS fanatics talk about Java's "huge runtime" when Node and webapps use stupid amounts of ram. Java's memory efficiency is stellar in comparison.


No, Swift requires "any as? Cast" which returns "Optional<Cast>" (or you can use "any as! Cast" which at least crashes instead of happily proceeding with the wrong type).


Your critique is about JavaScript, not about TypeScript.

Your argument is that TS blindly trusts 3rd party typings, but Kotlin has the same exact issue! In fact the Kotlin docs say to use TypeScript typings, or "dynamic" (read: unsafe) mode for 3rd party libs. So I would expect the same level of safety between TS and Kotlin when it comes to 3rd party libs.

I personally prefer TS because it's safer: with literal types and mapped types, my code is far safer than the equivalent Kotlin. It will surprise you how often you use these features.


To add to that, TypeScript is a superset of JavaScript, whereas Kotlin is a new language you'd have to learn.


> Since Java has always been strongly typed and has a ton of libraries available

Means nothing for alt-Java languages' JS target. While the host language gets the Java ecosystem for free, to replicate on the client every Java library needs to be cross compiled.

It's a non-trivial endeavor, one that ClojureScript and Scala.Js can largely avoid due to their already having a rich set of cross compiled frameworks and libraries in their respective ecosystems.

Not sure what the story is with Kotlin here, seems pretty tightly coupled to Java.


The Java classpath (built in API) will be an issue possibly. It's easy to compile third party libraries statically with your app. Just build a fatjar with maven shade and strip it with progaurd. You application will be only the Java runtime and code you're actually calling.

I've tested this with Java console apps and it makes them very small. I'm guessing you could get your app size under 50kb


I think that ClojureScript fits this criteria as well.

1. The resulting file size is great, heavily optimized and tree-shaked with Goog Closure Compiler. It seems Bucklescript does even better in this regard!

2. It's there, easy to use, does what you expect. A++ would interop again.

3. The ClojureScript community has some of the best libraries for web development such as DataScript, Specter, Reagent, Re-frame, Om, Rum, etc... Not to mention all the other cool built in stuff. core.async, core.logic, core.spec have been invaluable to me.

4. In my experience, you can re-use most of your core Clojure code in CloureScript. Just put them in a .cljc file. There are platform specific APIs as well, and those will be specific to your platform of course.

The only annoying thing is that you have to define your macros in a different file as your .cljs if I recall correctly.

5. The compiler is fast, but to be honest it doesn't even matter because of the state of the art tooling and browser integration you get during development, you don't have to recompile the project after saving a file. If you think Webpack has nice reloading features and dev tools integration, wait until you connect to the browser via a Clojure REPL directly from your IDE (or terminal). It's just bliss.

So here's my take. From a *-to-js language infrastructure point of view, we already have multiple good choices. However, from a language design/culture perspective, both of these languages are esoteric and most likely always will be. They won't catch on, like TypeScript might. Lisp isn't new. ML isn't either. There's a reason they haven't taken over Java on the server side of things for example.

For the foreseeable future, these languages exist just for the minority of programmers who have decided they want something better.

You can have both, so the question is, what's your poison? LISP or ML?


I second Clojurescript. Peter Hunt, the creator or React, was heavily influenced by Clojurescript and David Nolen.


I think he goes by Pete ;)

Edit: While I'm here, might as well link to the Simple Made Easy talk by Rich Hickey. The other thing (aside from inventing Clojure) that gave him prophet-like status in the community.

https://www.infoq.com/presentations/Simple-Made-Easy


Rich Hickey is one of the rare breed of thinkers in the programming world whose ideas have great relevance even if you're not interested in the language he invented.


Any good tutorial for Kotlin as a JS replacement? I am one of those people hating JS (and I did some very advanced JS web apps pushing technological possibilities) and would love to have something sane before WebAssembly can completely obliterate JS and I can switch to whatever language I like. Thanks for any hints!


> before WebAssembly can completely obliterate JS and I can switch to whatever language I like.

This is exactly what I'm waiting for.


I never tried Kotlin, but I'm working with Scala.js since 1.5 years and am very happy with it: http://www.scala-js.org This made me love the frontend again.


I'd really like this too, especially to see what it looks like in a react native world.

Being able to compile to 2/3 platforms would be a huge plus


>10.000%

To clarify, you mean 10000%, right? My American brain really wants to parse that as a (very precise) 10% improvement.


No, he means 10.000 which in parts of Europe is the same is 10,000 in the US. 10000 is the same thing as both. What's strange to me is that you seem to know this but still want to say something about it.

Its like an Englishman saying colour and you saying, "you mean color, right?" Just seems unnecessary.


>What's strange to me is that you seem to know this but still want to say something about it.

Because on a world-wide message board it's still inherently ambiguous. My comment was meant to serve two purposes. First, to draw attention to the ambiguity for others who use `.` as a decimal separator and read "10.000" as "10" (as I very nearly did). Second, to seek clarification because there is a non-zero chance that the OP is in fact a precision-minded person who saw a small productivity improvement when switching to Kotlin.

>Its like an Englishman saying colour and you saying, "you mean color, right?" Just seems unnecessary.

More like when an Englishman says "biscuit". in many contexts I would ask for clarification because my definition of "biscuit" is different from the common British usage, but it's also possible that the Englishman knows this and really does mean "American biscuit".


As an American who moved to the UK, I second your defence.

Awareness that you might be misinterpreting something and seeking to get clarity is a virtuous habit, both in programming and in productive discourse.


As an Englishman who still doesn't quite understand what an American biscuit is or why on earth you would put gravy on it, I second your defence too. It was a perfectly polite clarification.


If you've not actually experienced them in person, it might help to think of them as small savory (not sweet) cakes, typically served hot. Generally salty and fairly high in fat. They serve much the same role as croissant, but from an area where much of the flour was "pastry" flour which lacks the structure and tensile strength for yeast - raised bread.


An American biscuit is actually a Scottish scone. (Note, not what most people in the US or England know as a scone but a specific item historically made in Scotland that is identical to the US biscuit).

Source: my grandfather made them.

As to gravy: yes. Odd.


FWIW, I read it as 10% and would not have had it fixed if not for your comment.

I also felt spending an hour for a 10% productivity boost was well worth it, so it didn't strike me as odd.


A 9.999% boost wouldn't be worth it though, so I appreciated the extra precision.


Sorry I didn't respond very timely, but after considering the comment chain, I think perhaps you are right. The irony, now, is my comment was the unnecessary one.


I think you're reading into it wrong. 0xffff2 isn't correcting the parent, rather trying to clarify that by saying 10.000, that would be equivalent to 10000, since in America we use commas instead of periods for thousands denotation. We can't automatically know where people live and what standards they use, so we ask to clarify.


It's not a matter of geography. It's a matter of language. In English, a period acts as the radix point and a comma acts as a separator. It's a common error for people who learned English as a second language to use the convention of their native language when writing in English.


No, it's a matter of geography (or should I say locale). Raised in South Africa, we English speakers were taught to write "ten thousand and forty one-hundredths" as

    10.000,40
which is exactly the opposite of the US based

    10,000.40
So it's locale rather than language that determines this.


> source = "date"

> source = "produktname"

Honestly that doesn't look "completely typesafe": what are those "source"s? Don't they refer to another element? What happens if you make a typo there?


I wager there is type inference going on and that the IDE will supply red squiggly lines beneath the expression if the author were to supply something that would not one way or the other convert to the types that source can consume.


> I wager there is type inference going on

What will the compiler infer other than a value of type string?

> to supply something that would not one way or the other convert to the types that source can consume.

Well, clearly `source` takes a string, so it will happily accept "produckname" and blow up at run time.

Short of macros I know of no other compile time mechanism that would enable "safe" strings. The usual workaround is to not use plain string values at all and wrap in a sealed type.


It maps to database fields. The compiler checks that it's a string, but the rest is done by `admin-on-rest`'s mapping.


This is from the JS-library "admin-on-rest", that I use (via bindings). It's possible to introduce type-safe wrappers here as well.


I did the same thing when implementing [TodoMVC](http://todomvc.com/). You can check out the results [here](https://github.com/AppCraft-Projects/todomvc-kotlin). I will never write javascript again if I can help it.


Is the Kotlin version example available to run off the site? Poked around for a while but can't see it..


No, I did not submit it yet (may never will). It was created for a talk at Kotlin Budapest Meetup.


Thanks. I loaded it in Idea. Just need to figure out how to run it now...


Hey this sounds like a great setup. I've been wondering if Kotlin -> JavaScript could work for React. Do you have some more documentation or code that you could share on how to setup a project?


Given that this was merely a week ago and you had to write your own bindings, I'd wait a bit with your evaluation to see whether other annoyances come up. That productivity boost is not likely to remain that high :)


I saw the light last week as well. You can combine this with Quasar to get Erlang style concurrency. I wonder if you can somehow hook up, idk RxJS on the client with RxJava on the server for seamless integration.

The JSON story is also amazing.

This stack is gonna be the biggest deal in the world.

Not to mention that you can run it on Android and soon enough iOS. This is unprecedented.


Sorry, I firmly believe that nothing gets Erlang-style concurrency except Erlang. Other ecosystems may get something that mimics Erlang's concurrency, but the imitation is skin-deep.


I know, I played around with quasar a couple of month ago.


> Writing the react-bindings took me an hour,...

Do you mean generic 'use react in kotlin' bindings? If so, have you published them or would you consider doing so?


Yes.

I have not published them, because

a) they use the same method names like the `kotlin-html` package ("div{}" et. al.), only they create ReactElement instead of manipulating the dom. This could be confusing.

b) The type-safe scoping mechanism, so that each scope has it's correct prop-setters and won't inherit setters from a scope further up is rather complex. It uses extension methods with multiple receivers plus operator overrides for `invoke()`.

That is rather complicated to follow so I want to try it out for some time to check if there's confusion or subtle bugs.

c) I haven't optimised for (allocation-)performance yet.

d) I'm using an early-access version of kotlin 1.1.4 which isn't out yet.


If it only took an hour, it can't be very type-safe / comprehensive.


Here is a good tutorial if you'd like to try it yourself:

https://kotlinlang.org/docs/reference/type-safe-builders.htm...


Did you follow a framework or roll your own? I'm thoroughly fascinated with isomorphic kotlin, but haven't had a chance to dig in yet.


With kotlin I seldom need a framework, because the standard-library is so rich.

In general, when I tend to follow a data-flow ("redux" for JS people) architecture, but have a different approach when it comes to side-effects: My state is always a serialisable description including running side-effects. So even network-requests can be reconstructed from a state-file.

Also I decouple View/React from the actual state via interfaces.

Meaning my state doesn't necessarily contain the data in the format my Views need, but it's able to supply the data via delegation.

If I need background-threads I use actors / CSP.


This sounds really interesting, do you have any examples or a blog post explaining this in more detail?


No, but I'll might write it up at some point.

So much to do, so little time ;)


Curious what the output of this is(photo), it looks like it would create something with the div/textfields? Is it an inline span element that is editable but not an actual <input type> ?

I'm behind on frameworks, I just build with html/css/js/php


Well, if I had to pick a single recommendation for improvement of any web-development-cycle, it would be `Tachyons.css`:

http://tachyons.io/


There are a few concepts that I don't personally use but see on a page I can literally build anything drawn on a piece of paper (for web) but the question is how long will I take?

Also the security aspect and whatever with regard to using Laravel vs. using your own PHP.

I don't know I'll figure it out.

Thanks for the link to tachyons.css


More tips: * Never use object-relational mapping * Use postgreSQL instead of mySQL * (optionally) switch from PHP to python


Hi, would you mind telling which IDE you are using? This sounds very interesting.


While you can do Kotlin development in Eclipse (and others), IntelliJ is basically _the_ IDE for Kotlin, since they are both developed by the same company (JetBrains).


IntelliJ IDEA, Community Edition.


Java? why?


Because it's probably the most-advance virtual machine out there. It has a massive ecosystem, many years of testing and battle-tested devops-tooling. It has everything.


Those aren't really arguments for it.


which do you like more React Native or NativeScript(Angular)


Never used Angular nor NativeScript.

I get along with ReactNative, it's decent. The data-application part of my last android-app was already written in (JVM-)Kotlin and in the futures the UI will be as well. ;)

I recommend my styling library for React-native: https://github.com/tachyons-css/react-native-style-tachyons


TL;DR: JS with a ton of make up and tooling to not write JS is not as horrible as it used to be.

Well. That doesn't make it awesome either.

You just traded some problems for others.

Like the damn source map never working correctly, the build time being longer and longer, and the never ending list of plugins you expend every day after stumbling on yet another small-minuscule-not-that-important-I-swear detail.

The tool chain you spend more and more time on, despite all the "5-minutes" bundles provided by facebook or on githubs.

Explaining things to new comers has never been as difficult as it is now. Teaching is a pain.

Choosing your stack is a dangerous bet, and the odds and steaks are changing all the time.

If you opt-in for a flux architecture, you will soon write Java-as-in-the-90 on the frontend instead of Javascript, with so many adapters and design patterns as layers you will become angry.

If you don't (you-totally-don't-need-redux-to-use-react-guys) then most documentations and tutorials will not answer your questions, and you are own your own solving every single problems. Even the simplest ones, like redirecting on a route after data changes and closing a panel at the same time.

"Libs, not framework" means you need to relearn everything, rewrite a lot of code, tests and doc and renew maintenance for each new project. Meanwhile nobody agree on what a the proper stack is.

JS, despite all the paint on the rust, still has the old gotchas. This is still weird. ";" is still auto inserted. "==" still compares like nothing else. Errors come in different so many different forms it's not funny. Basic maths assumptions like commutativity are out of scope. Still no namespaces, but instead we use monstrosity like webpack and incompatible import systems to encapsulate things. Stdlib still doesn't have essential things like hashing, string/date formatting or encoding. Even basic operation like removing an element from an array using an index is a pain.

No, I'm sorry, JS has not become awesome. We just arrived to a point were we accepted we have everything to built with it and agree to pay the huge price for it. That's all.

Projects like vue.js makes me think there is still hope we end up with elegant tools from people who care. But right now I just embrace the madness and make money with it: all those poor customers don't realize the trap the current mindset lead them to, and I have so many solutions to the problem they should never have had to sell them.


>No, I'm sorry, JS has not become awesome. We just arrived to a point were we accepted we have everything to built with it and agree to pay the huge price for it. That's all.

Yep, this is the crux. ES6+ has finally made JavaScript look more or less like the languages we were using in the mid-90s, so I appreciate that, but it's not like it's some glorious boon to the developer community.

Any gains from the new semi-tolerable semantics are quickly overwhelmed by requiring layer-upon-layer-upon-layer of crap, including hundreds of dangerous random modules from GitHub to compensate for the virtually non-existent standard library and a "build pipeline" that consists of several unrelated runners, bundlers, transpilers and transformers to make code that's actually usable in real environments.

JavaScript is a tragedy for the development community from start to finish, and its increasing prominence should disabuse us of the notion that development is dictated by meritocracy or any such fantastical nonsense like that. Marketing and groupthink have just as much pull here as anywhere else (if not more because so many of us egotistically believe we are immune to it).


Everyone complains about the build tools, but they simply haven't thought through the issues.

Let's say you were writing the web using Python. New browsers run v3.x, but old ones run 2.x or even 1.x. Further, features in newer versions of v3.x won't work on older versions of v3.x. New browsers could include all three runtimes, but old ones would be SOL.

How do you use v3 features and target v2 or v1? You must transpile knowing that newer browsers also have v2 and v1 engines included too.

You have hundreds of Python files in your system. Delivering hundreds of files is simply not practical on HTTP/2. You combine them and now you have webpack.

What about libraries? As big as the standard lib is for Python, it doesn't do everything. You use pip or conda and now have npm/yarn.

What about code consistency? The solution is pylint.

What about testing? Add that to your chain as well.

It's the unique issues of the web -- NOT Javascript -- that makes the build pipeline what it is. Until a few short years ago, these things weren't even possible. Today, if you know node/npm, webpack, babel, and eslint, you know the overwhelming majority of build processes.

I'd finally add that make, Jenkins, etc are far more complicated to learn than the JS systems.


The original crappy design is definitly a problem with JS: the typing/testing, the lack of namespace import, the emptyness of the stdlib. Half of the problems we have today are directly correlated with this.

Most of our tools are not here to make things better, but to avoid sucking too much.

So yes, forward compat is an issue. But that's hardly the one I'm complaining about. I'm really ok with not being able to use spread, but I can live with it. I'm not ok with having to use npm + webpack to download, install, isolate and bunddle a remote lib to do a leftpad.


Add to this the WTF ES6 added to the lanuage like different "this" scoping for arrow functions. Great. Now I have 2 headaches instead of 1.


I'd say you have one. If you had one before, you didn't know what really happened when you went `var that = this;` and aired your opinion about how `this` is being stupid. So you got the arrow function, where `this` acts the way you expected before, when you said it was stupid. You can't complain about both.

The scoping of `this` has never really been too hard to understand. I learned it my first week doing JS.


Agreed, I stopped recommending React to beginners. I still love it and think it's the future, but in the sense that it's the new low-level. Eventually I think it will be standard to compile futuristic, high level, built-for-apps languages into React code. But for now, makes sense to just use a batteries-included framework. I don't know what the most sure shot is there though. Ember? Vue?


Mithril. Much simpler than anything else and batteries included. It's a great way to get beginners into front-end frameworks and gain knowledge that transfers easily.


Indeed. I use it to introduce beginners to modern front-end frameworks here: https://medium.com/front-end-hacking/how-it-feels-to-learn-j...


Mithril is nice. W.r.t. going for batteries included, it's still a bit minimal for my taste. Personally I would lean towards something more dogmatic, in the spirit of Rails. For example, things that I would miss from Ember: ember-data, models (with relations), controllers, opinions, integrated tooling, etc ... But Mithril looks cool I've been meaning to play with it too. You're right that skills gained from learning Mithril will be more widely applicable to general front-end dev than Ember.


How about rails?


Rails is great, but where it really shines is server side apps, content sites, blogs, CMSs, etc .. If you know you're building purely a SPA, Rails isn't really the right tool for that.


I'd argue that more than half pure SPAs do not need to be SPAs, and can be written effectively in Rails with someone who knows it well, in less time, with less bugs, and more test coverage.


  This is still weird. 
Use variables. Not this.

  ";" is still auto inserted. 
If you insert the semicolons yourself and don't depend on the auto insertions, you don't have to worry about the edge cases where the lack of a semicolon would introduce a bug.

  "==" still compares like nothing else.
Use === if you want to be explicit.

  Errors come in different so many different forms it's not funny. 
I agree, but this is only a problem with new API's like service workers, what where they (TC39) thinking when introducing unspecified errors !? That can't even be detected !! There's already a convention to use err.code to specify type of error, use that please!

  Basic maths assumptions like commutativity are out of scope. 
The commutativity is the same like in classic Maths I think, it's just he floating point errors that mess things up.

  Still no namespaces, but instead we use monstrosity like webpack and incompatible import systems to encapsulate things. 
The module system (require) in Node.JS comes from user-land, and can be implemented in pure JavaScript, so you can use it in the browser too!

  Stdlib still doesn't have essential things like hashing, string/date formatting or encoding. 
We have .toString, parseInt, atob, btoa, etc. The rest can be implemented in user-land: var md5 = require("md5")

  Even basic operation like removing an element from an array using an index is a pain.
I think it's fine. If you use a named list {} you can "delete foo[bar]"


> Use variables. Not this.

You can't if you use react.

Besides, JS is the only language I know where half of it is recommended to not be used.

> If you insert the semicolons yourself and don't depend on the auto insertions, you don't have to worry about the edge cases where the lack of a semicolon would introduce a bug.

But that's not the point. The point is my students will forget the semicolon in some code that is not properly checked, and it will work. Most of the time. Until it doesn't.

> Use === if you want to be explicit.

No shit sherlock ? But again, half of the language is forbidden. And you know somebody is going to write != instead of !== one day, tired.

> The commutativity is the same like in classic Maths I think, it's just he floating point errors that mess things up.

Nope. Nope. Nope. Nope.

$ node > [] + {} '[object Object]' > {} + [] 0

> We have .toString, parseInt, atob, btoa, etc.

Come on, you never used Java, Perl, Ruby, Python? Any language with decent string formatting ? That doesn't need a leftpad dependancy ? That can format date without importing 34ko of moment.js ?

> The rest can be implemented in user-land: var md5 = require("md5")

And then you get the current 3Mo pages we all hate. Are you even serious with your arguments or is it trolling ?

> I think it's fine. If you use a named list {} you can "delete foo[bar]"

A mapping is not a list. It doesn't perform the same. You can't push and unshift. You can map on it without Object.stuff. Length is a costly operation. Concat without spread is a pain. And how do you get the "next 3 elements after the 2nd" ?


> JS is the only language I know where half of it is recommended to not be used.

Jamie Zawinski (who else) about C++ in 'Coders At Work': When you’re programming C++ no one can ever agree on which ten percent of the language is safe to use.


> And how do you get the "next 3 elements after the 2nd" ?

.splice(2, 3) (am I missing something?)

> > The rest can be implemented in user-land: var md5 = require("md5") And then you get the current 3Mo pages we all hate. Are you even serious with your arguments or is it trolling ?

md5 node lib is 32kb unbundled. If you meant 3Mb pages that's ridiculous. Modular necessity at the hands of the user is good, and it's something that's been present in every project i've worked on in a less granular fashion than modern npm-driven apps can deliver.


OP was talking about trading [] for {}. You can't splice on {}.


well, objects are not iterables... ??? unless you decide you want them to be, in which case you can make them such and design them in a way that they work as such?

The least elegant way is Object.keys().map(key => etc) which is really not that hard to work with

edit: it's a phony premise to begin with actually. Iterables have order, objects have mapping. I am less experienced with other languages so I probably don't understand OP's statement clearly. I just think OP's context is lazy thought rot about what's becoming a fairly elegant language. BUT I'm a noob.


> Besides, JS is the only language I know where half of it is recommended to not be used.

That's what you get for having backward compatibility I guess. If the standards committee would break my old code I would probably quit and start a sect. I would call it "ReactReduxReduce" (RRR).

> The point is my students will forget the semicolon in some code that is not properly checked, and it will work. Most of the time. Until it doesn't.

Some people prefer writing JavaScript without semicolons. How do they not have bugs all over the place ? :P


> Some people prefer writing JavaScript without semicolons. How do they not have bugs all over the place ?

The same way that people who write with semicolons avoid lots of bugs: linters and transpilers and tests.

That said there is only one rule to remember when not writing semicolons, the easy to remember "winky frown" rule: all frowns must wink if they start a line/statement. ;( ;[ ;`

;(The last two are quite rare in my experience.)

It's not that tough of a rule to remember.


Our projects' linting rules specify no semicolons, except when necessary; this means that we will _very rarely_ write something like this when we want to iterate over a small literal array:

    ;['foo', 'bar'].forEach(function (f) {
      it(`has an ${f} field`, function () {
        expect(......)
      })
    }
That said, we tend to use that construct extremely rarely, such as in a few test cases where we are doing the same kinds of things on two groups of items that need different descriptions.


Most of my usages are Typescript type assertions:

    ;(thing as Type).methodINeed()
If it weren't for these I mostly wouldn't need semicolons at all, sometimes I refactor to:

    const thingType = thing as Type
    thingType.methodINeed()


> How do they not have bugs all over the place ? :P

Who says they don't?


They don't.


> Some people prefer writing JavaScript without semicolons. How do they not have bugs all over the place ? :P

Some people prefer to have sex with children. How do they not get jailed?


Ughhhh... what?


It's amusing how my karma went up and down depending on whether the given person had understood the joke or not; eventually normalising at exactly 1. Nevertheless - I can't blame them as there is no way to tell the irony on the net.

Who I can blame is the original parent of this post who was quite confidently stating that omitting semicolons never causes any issues in his code (which is either a statement bounded by scale at which it works for him or it is not error-prone only in specific situations); and then just edited it so that it did not contain that specific line.


>Besides, JS is the only language I know where half of it is recommended to not be used.

Then you probably have never heard of the most successful (by the number of infrastructure written in it with amounts to almost everything in commercial OSes, network services, Google's search backend, most games, most commercial applications, databases, compilers, the JVM, all browsers, etc) -- C++. Where "half of it is recommended to not be used" also.

>No shit sherlock ? But again, half of the language is forbidden. And you know somebody is going to write != instead of !== one day, tired.

No shit, Einstein. That's why people use linters. In C you can corrupt memory with a stray ++ or alter flow with = instead of ==, fuck things with & instead of && and more. If we threw languages because they allow for errors, we'd have no language left.

>Come on, you never used Java, Perl, Ruby, Python? Any language with decent string formatting ? That doesn't need a leftpad dependancy ? That can format date without importing 34ko of moment.js ?

So? You've never heard of a language without "batteries included"?

>And then you get the current 3Mo pages we all hate. Are you even serious with your arguments or is it trolling ?

Are you? Before the problem was that there's no hashing support, now that hashing support is third party and makes pages bigger. As if a language should include everything in its standard library. I assure you most of the "3MB pages" is assets like images, not JS.


"C++"

C++ also gets a lot of hate for half of it being forbidden to use.

"If we threw languages because they allow for errors, we'd have no language left."

Correction: we'd have Ada, some of those "prove your program is formally correct" metalanguages, and possibly Rust. Probably some others with which I'm not familiar.


>Correction: we'd have Ada

Ada allows for errors just as well.

http://www-users.math.umn.edu/~arnold/disasters/ariane5rep.h...

It's a cargo cult/myth that was circulating from back when I was in university that Ada is some super fault tolerant language because they use it for rockets and stuff and because they designed it to be super secure.

It was indeed designed to be more secure than C and to be an official government/military use language, but no "super secure" and allows for errors just fine.

Besides, they do rockets in C just as well (with certain rules).


"Ada allows for errors just as well."

    Although the source of the Operand Error has been 
    identified, this in itself did not cause the mission to 
    fail. The specification of the exception-handling 
    mechanism also contributed to the failure. In the event 
    of any kind of exception, the system specification 
    stated that: the failure should be indicated on the 
    databus, the failure context should be stored in an 
    EEPROM memory (which was recovered and read out for 
    Ariane 501), and finally, the SRI processor should be 
    shut down.
In any case, I'd argue that converting a 64-bit float into a 16-bit integer is a much different class of problem from mixing up assignment and comparison operators. But yes, you're right, even Ada is not perfect.

"Besides, they do rockets in C just as well (with certain rules)."

Yes, they do. Those "certain rules" are codified in the MISRA C standard (or derivatives thereof, like with the JPL and JSF coding standards). Said standard is way more strict than the sort of thing normally implied by "C programming".


>In any case, I'd argue that converting a 64-bit float into a 16-bit integer is a much different class of problem from mixing up assignment and comparison operators.

Is it though? Because in the end it's the same issue of conversion between types (coercion vs casting, but still).


A linter solves 100% of the "issues" you describe related to ASI and type coercion. Every single major editor or IDE has support.

> [] + {} '[object Object]' > {} + [] 0

The first case deals with an array, an object, and a concat operator. The second case deals with an empty code block, an array, and a unary math operator. None of that has anything to do with commutative properties because neither unary operators nor string concatenation are commutative in ANY language.

> Come on, you never used Java, Perl, Ruby, Python? Any language with decent string formatting ? That doesn't need a leftpad dependancy ? That can format date without importing 34ko of moment.js ?

The standard date object sucks, but that's no huge wonder because they were required to make it behave like Java (it even has an old Java Y2K API bug where it returns only the last two year digits).

We used to have horrible proceedural, class-based math libraries. Next we moved to underscore. That was replaced with a much faster lazy libraries. The current trend is toward even faster transducer-based solutions with more functional options as well. Which would be the correct language standard?

Having been bitten by bad APIs in the past, there's been reluctance to move too quickly in adding extra APIs to the core language. I think the current solution of adding good primitives and leaving the rest to good libraries is an ideal solution (after all, JS can add things, but old mistakes are forever).

> And then you get the current 3Mo pages we all hate.

We had a multi-MB page. Tree shaking got rid of most of it. Moving the biggest libraries to shared CDN versions that lots of sites use gets rid of a lot of load time as well. Using webpack to chunk your site also reduces the payload to a manageable size.

> A mapping is not a list. It doesn't perform the same. You can't push and unshift. You can map on it without Object.stuff. Length is a costly operation. Concat without spread is a pain. And how do you get the "next 3 elements after the 2nd" ?

A sparse list uses a map (in fact, Array is defined as a special case of a standard Object -- JITs simply optimize to more efficient data structures when your data allows). Further, if you start deleting in the middle of a list, it will not be optimized past a linked-list anyway (in ANY language).

If I were needing to do a bunch of item removal, I'd use this.

    var removeNth=(x,s)=>x.splice(s,1); //a bit faster
    var removeNth=(x,s,e=s+1)=>x.splice(s,e-s); //a bit more flexible
    Array.prototype.removeNth=function(s,e=s+1){this.splice(s,e-s)} //a bad idea, but possible


> If you insert the semicolons yourself and don't depend on the auto insertions, you don't have to worry about the edge cases where the lack of a semicolon would introduce a bug.

I think this is not correct. It will still insert a semicolon where you don't want one. It's not like there's a compiler flag to turn insertion off.


That's not how it works, semicolons are only automatically inserted if they were omitted.

Use semicolons, lint the code, ????, profit


I just tried to get the linter (JShint) to break some valid code, but it didn't. So you can actually rely on the linter to insert the semicolons for you. It would be interesting to find out if there are any cases where the linter will insert the semicolon in the wrong place.


The browser somehow detects that the missing semicolon wasn't omitted and doesn't add it???


No. If it's missing it's inserted obviously. That's why you shouldn't omit it.

Here are the rules for parsing if you're interested

When the program contains a token that is not allowed by the formal grammar, then a semicolon is inserted if (a) there is a line break at that point, or (b) the unexpected token was a closing brace.

When the end of a file is reached, if the program cannot be parsed otherwise, then a semicolon is inserted.

When a "restricted production" is encountered and contains a line terminator in a place where the grammar contains the annotation "[no LineTerminator here]", then a semicolon is inserted.


  > If you opt-in for a flux architecture, you will
  > soon write Java-as-in-the-90 on the frontend
  > instead of Javascript, with so many adapters
  > and design patterns as layers you will become angry.
That's not necessary. It depends where you're working.

I agree that teaching the complete stack is a pain. I guess there is `create-react-app` to help you there, but its scope is very small: you're not going to get static typing for example.


Well, if you want routing, you need a provider, and if you want to pass your store to a component, you need a container, and if you want to react to store change, you need a reducer, and if you want to make async action with your store...

There is an "-er" somewhere at every step.

You pass callbacks here and props there, and then reference them the other way around. And then you plug stuff in your componentWillReceiveProps, or is it in compomentWillMount or componentDefinitlyDidMountISwear ? But wait this is a new style class, so you have to call super(props) in constructor insteat of getInitialState unless you have a super Esx plugin but then remember that your onClick callback need to rebind this otherwise you'll get 'attributeOnThis' is undefined somewhere in your bundle and you'll have a fun time.

When you come from flask, Django or Ror, having to deal with such API feels like going back to before the 2000 bubbles, where corporates tried to port their knowledge to the Web.

It does not feel agile at all.


I'm sorry but a `reducer` isn't a 90s-era Java concept at all [0], and you don't actually need to use any of those other things. This is beyond ridiculous.

[0] https://en.wikipedia.org/wiki/Fold_(higher-order_function)


No but writing HTML directly in your class is soooo late 90s like when we used to write Java Servlets!

All this has happened before. It will happen again


You write syntactic sugar <div className="foo">abc</div> to turn into React.createElement('div', {className:'foo'}, 'abc') which generates an object {...stuff, tag: 'div', attrs: {className: 'foo'}, children: 'abc'}. Your final object is then compared to the previous object and any differences are manually written to the DOM in an efficient order.

Hardly comparable to Java Servlets.


Try Clojurescript with Reagent or Reframe. The whole React pipeline of bits and pieces just goes away.


My biggest problem is "the complete stack." Which one? How many months will it be the blessed way of doing things?

As soon as I get some work outsourced, here it comes yet another build system and yet another complete stack I have to get expert at.

Javascript lacks a standard library (a mistake from the beginning) as well as standard tools (can't blame Netscape for this, but today we could totally come up with something more definitive.


There is no single blessed "complete stack" for React and there never will be. That is a feature, since it is a view library only.

It sounds like you're looking for a full framework, e.g. Angular or Ember.


If JavaScript had a standard library from the beginning we would be replacing it now because it wouldn't support Unicode or promises or async or whatever is coming next.


The stdlib can evolve with the W3C the same way the language evolves.


The w3c cannot break the web. Once something is in the language a certain way, it stays (technically, there have been a couple small breaking changes, but the fact that you don't hear about them speaks to their size and impact)


You mean we're stuck with the legacy stuff forever.


React was released in 2013. Redux was released in 2015. If you'd picked them then you've had a very long amount of time using the same tools.


I'd hardly call 4 and 2 years (respectively) a "very long time".


It is a very long time in js world of things


We don't have precognition. It is not safe to pick a brand new framework for an important project right away, we have to wait a bit first to make sure it is being maintained well.


Brilliant. Absolutely brilliant. Bravo


FYI, you don't need to use `this`, omit `;` or use `==`.

Also JavaScript is commutative as long as FP64 is. Out of curiosity, what's the pain with removing an index using `splice(index, 1)`?


> FYI, you don't need to use `this`

You do if you use react.

> omit `;` or use `==`.

Mistakes are made all the time.

> Also JavaScript is commutative as long as FP64 is.

Nope.

$ node > [] + {} '[object Object]' > {} + [] 0

> Out of curiosity, what's the pain with removing an index using `splice(index, 1)`?

Finding it. Remembering it. Getting it right. Reading it back.

Remove the 3rd and get it in Python:

res = a.pop(4)

In JS:

var res = a[4]; a.splice(4, 1); // usually a comment to remind you that you pop

It's verbose, ugly, unintuitive.

It's like this : https://xkcd.com/1168/

But for JS.


> $ node > [] + {} '[object Object]' > {} + [] 0

Note that that has nothing to do with math. It has to do with braces being used for both blocks and object literals.

Of course, I'm not too happy about the automatic coercion of everything and anything to either strings or numbers, but if you want consistency, try parentheses, or a + [], where a = {}.


Haven't used React but I'm sceptical. In what case do you need to use `this`?

The only time I believe I've used this was maybe using a class? Which is shit so why would I want to do that anyway?

Okay, so there are footguns. Don't use them, use a linter, problem solved.

That doesn't look like math. What are you saying exactly?

What's your problem with let res = a.splice(4, 1) ? I don't understand really, the method name and extra parameter?


fyi splice returns the slice you remove, and ES6 allows array deconstruction so you could just use `var [res] = a.splice(4, 1);`.


>> FYI, you don't need to use `this`

> You do if you use react.

You can use functional components.


plain old javascript is perfectly fine. es6 is better. if you can't write good apps with js it is because you aren't a good programmer and you wouldn't be able to write good apps in any language.


Omg, so this guy thinks he knows why I'm hating Javascript? Well, it's definitely not because of the lack of types, or because without Prettier my code looks shit, neither would it be the lack of E6/ES7 features since I'm using Coffeescript 2. No, I hate Javascript especially for it's conitnuously changing ecosystem being forced upon you. You named Dan Abramov? Ah, the guy who deprecated almost all flux in favor of his own idea (Redux), or by deprecating React Mixins, because he thinks Mixins are bad, Higher Order Components is the new holy grail?

If I am looking for a job as a Javasript developer at the moment it is not about my coding skills, it is about my willingness to adopt all those hyped technologies, and the author of this article is just making it worse.

I also hate Javascript for all those people reading this that think I don't understand it yet, and are going to explain me how great ES6/ES7, Promises, and/or Typescript are. Please don't.


> Ah, the guy who deprecated almost all flux in favor of his own idea (Redux), or by deprecating React Mixins, because he thinks Mixins are bad, Higher Order Components is the new holy grail?

How dare the man spend hours and months creating something others ended up finding so valuable they discarded their own things.

If you really prefer the bug-inducing mess that were mixins, you can still use React.createClass (with full mixin support) by using the react-create-class module: https://yarnpkg.com/en/package/create-react-class

Which, by the way, is maintained by the same people you are so upset with. For changing their mind about the API of something they gave you for free.


> If I am looking for a job as a Javasript developer at the moment it is not about my coding skills, it is about my willingness to adopt all those hyped technologies

If you're looking for a job as a developer I hope it's always about your ability to adopt to changes and new technologies. Because that's what distinguishes a developer from somebody's "nephew who's really good with computers" and is willing to work for scraps.

Any formal education worth its salt is about giving you that ability rather than just teaching you the status quo. If you want a stable ecosystem that doesn't change, try specializing in legacy technologies. There's still a ton of software written in languages that are well past their prime and large companies will pay good money for people willing and capable of working on that.

Maybe you should stay away from JavaScript for the next 20 years and come back when people consider it quaint and archaic and don't try to apply new ideas to it anymore. This isn't hyperbole, this is an honest suggestion.


Sure, but adapting as a JS developer is mostly about relearning how to do the same thing using different libraries and frameworks.

As an embedded developer I am able to build upon my existing knowledge and am deepening my skills in embedded, Linux, C++, etc. I'm not learning new programming languages and operating systems every couple of months.

And this is how it should be, otherwise you'll end up being always average, no matter how much you learn.


> relearning how to do the same thing using different libraries and frameworks

This is hell to me, such nausea-inducing inefficiency. I feel like I'm wasting my time and cluttering my brain needlessly in those scenarios and it drives me mad. What if you were a woodworker and every few months all the tools and equipment in your shop changed in various subtle ways? It makes very little sense to me in the long run. True mastery depends upon some amount of consistency in your environment. It's the only way you can build on what you knew before (because it didn't change when you weren't looking) to do more complex and interesting things.


But think of all the sweet conference talks you can give after inventing the latest new shiny woodworking tool!


Direct DOM manipulation. Event delegation. MVC. MVP. MVVM. Component trees. These aren't libraries, they're not unique to JS.

I've been doing frontend development since the 1990s and in many cases I could still solve the same problems very similarly to how I solved them 10 years ago (except I would probably forego jQuery and use the web APIs directly thanks to widespread browser support).

The reason I instead spent my time learning Backbone and Knockout and Angular and React is that the kind of problems I'm solving has changed over the years.

Your characterization is also hyperbolic. You don't learn an entirely new way to do exactly the same thing and throw all the old knowledge away. Learning Backbone informed how I used Knockout, learning Knockout helped me better understand Angular, having used Angular I know what problems to avoid in React. All of it helped me build intuitions about possible caveats when looking at new tools and libraries.

I mostly don't write Angular code anymore. I haven't touched Knockout in years now. My contact with Backbone is also fairly minimal these days. But learning each of them made it easier both to learn new things in general and to understand other libraries better.

Also, React is the odd one out here. To fully understand Angular (1.x that is), I had to learn about its internals and unique concepts and terminology that are mostly orthogonal to my application but vital to avoid certain mistakes. With Backbone and Knockout the overhead was smaller but a lot of the effort in gaining proficiency was spent learning their quirks and idioms. With React there was some of that initially but all effort beyond that went into language features that come in handy outside of React and concepts that are useful beyond React or JavaScript.


When wasn't it like this.. raw js, NN4 DOM, IE4 DOM, W3C DOM, Prototype.js, mootools, jQuery, extjs, etc.

C/C++ also haven't sat still either, there are always new hotness in any language. For a language that interacts with UI asynchronously, JS has moved in a direction that tends to make it easier to user, even if it changes in the common use case. I remember the bad old days in the mid-late 90's, I'll take today's JS ecosystem.


Dude, Django and Rails have basically improved in their tech while staying conceptually sound and approachable.

This is a cop-out. You pretty much have to relearn the JS environment every other year. It's a colossal waste of time that only junior people would be willing to tolerate for a marginal (if any) productivity gain.


> Django and Rails

Django's deprecation policy is practically the same as React's, except React provides codemods for every release, allowing you to automate code migrations.

And if you think Rails hasn't changed, you've probably not been using it long enough to remember the early drama. Not to mention Django's Python 2/3 conundrum (also class-based views). Heck, Django's development on top of Python's is aptly comparable to e.g. React's on top of ES.


So what? React is one library in the ginormous pile of tiny little dependencies that come with any JS project that's large enough, and those don't have the same policy and are subject to the incessant churn of the ecosystem.

I've been using pretty much the exact same packages for a 5-year-old Django project with no need to migrate needlessly.

I've had to migrate JS apps that were just one year old and tiny, and the amount of pain was far larger than upgrading a 50k LOC Django project.


You sound quite fatigued! Here's what I suggest:

- Uninstall webpack for a month

- Download the few libraries that you can't live without

  * Put them in a script tag
- Disconnect from HN and Twitter. Better yet, the internet all together.

- Finish whatever you're working on in peace, and save Abramov & friends from your thoughts about how inconvenient technological progress is for you.


You've conflated needless churn with progress.

They're not the same thing.


You've somehow managed to put down the hard work of community leaders from your hind-sight high horse, and at the same time, disown responsibility for the choice of library/language your software was built on. Implying the fault is on them for doing their best to push the community forward, rather than on you for shipping software built on presumably new, unproven, and highly volatile foundations. Impressive, sir.


I guess we just disagree on what constitutes pushing the community forward.

I don't write javascript software, I merely have to experience the pain of using it.


Dan created Redux as a proof of concept experiment for a conference talk. I'm sure he did actually want people to use it, but based on comments he's made, he definitely had no idea it would became the de-facto standard state management tool for React apps. Frankly, he's spent more time telling people _not_ to use Redux if it doesn't fit their use cases than actually trying to advertise the library.


> because without Prettier my code looks shit

Prettier is a cool tool, but it's pretty trivial to press enter and tab every once and a while to format your own code.


Well, if you don't like learning then you can still use DHTML like it's 2003


Huh? Why is this a problem? Just use what you like, all the old techniques still work, you could use jquery if you like, nobody's stopping you.


If your only reason to hate a language is that it's making improvements (that you can't/won't keep up with), it would seem that language is doing something right


It's not that it's improving, it's that it's changing in every direction at light speed, and if you say went on holiday for a month offline when you come back the odds that you find the syntax and the ecosystem substantially different is very high. And whether all or most of these changes are indeed improving anything is doubtful. I personally can't follow JS anymore, it's a storm of not-so-news from every direction.


Since ES6/2015 the changes have been pretty minimal, so I disagree with your assertion. Since 2015 I find that async functions is probably the most alien addition... and the handful of others that are significant are mostly ignored or very natural extensions.

The shift from callbacks to promises is kind of alien, but frankly that was started well before 2015 even. The .babelrc I use for node projects is pretty simple as well, here's one I use for an AWS Lambda build...

    {
      "presets": [
        [
          "env",
          { "loose": true, "targets": { "node": "6.10.3" } }
        ]
      ],
      "plugins": [
        "syntax-dynamic-import",
        "syntax-object-rest-spread",
        "syntax-async-generators",
        "transform-class-properties",
        "transform-decorators-legacy",
        "transform-object-rest-spread",
        "transform-async-to-generator"
      ]
    }
So that's literally 3 things that aren't in spec yet, and a couple that work around the runtime not having them. Most of what's going in is already in, or relatively well established and on the way.

Now, you do have to include a lot more if you want IE11 support, but hey, that's a different thing. I'm not sure what exactly you're having a trouble wrapping your head around.


Don't compare JS (or any language) to any other language - or any language to another language. People wrote a lot about it (Your language sucks because... - type things). JS is just another language.

The JS ecosystem is wild and moving way too fast, but even that is not really the trouble with it: it's that it's being overused.

He mentions DHTML at the beginning, which was the perfect example of using too much of something: mouse trailing bouncy balls with falling snow, my, I don't really miss those days.

Yet we're here in 2017 and React & Co. is crippling the web. Plain simple news or a blog site rendering with JS? AMP, loading megabytes of Javascript, claiming to speed up the web? When your product is text, how about you serve text and maybe only boost it or do analytics with JS? I know it's not fancy, but for a lot of sites out there, JS based rendering is completely unneeded.

In case of web apps... A little while ago I listened to a talk of front end colleagues, claiming that we'll speed up the site by async calling some blocks, so the initial content will get down fast and the less important ones will follow. When I asked if we're measuring the very end render time - the one that heats the CPUs, because you offload the rendering to the client, which can get quite stressful - the answer was 'no', mostly because nobody knows how to do it. I also asked about how screenreaders will work with this, and they thought I'm talking about mobile, which is extremely sad, and no, I'm unaware of any screenreader-friendly JS based app. (Screenreaders are the programs literally reading out the text for visually impaired.)

Google and FB offers fallback, HTML-only solutions to their services, because the realised their things don't work on slow connections and/or slow devices. Maybe this should be taken as a sign.


2 quick points:

- The paradigm shift in writing interactive web pages in the React "write your app like a game that re-renders every frame"-style is extremely compelling. You are correct that there are plenty of largely static sites that do not need JS-based rendering, but for people wanting to develop single-page web apps or other interactive content, that mindset is a godsend.

- We recently re-wrote an ecommerce site with React and it is WCAG 2.0 AA compliant. To our knowledge, and to the independent firms that have audited our application, screenreaders have no problem with it. You still have to go through the diligence of all of the standard a11y-friendly techniques like semantic markup and thoughtful keyboard navigation, but React at least does not get in the way.


Another compelling use-case of React is the ability to use it as a better templating language ― treating HTML as a data structure instead of a string, better composability of the units of your UI, and the ease of rendering to a string.

It's an interesting question whether the tendency to overcomplicate a largely static site by implementing it as a single-page app should be attributed to the average developer or to the creators of the library though.


Screenreaders do work, but document navigation gets crippled above and beyond, SPA's tend to alienate visually impaired people.


While you are bringing up very valid points, I can't help but feel like your blaming the hammer for the shitty chair instead of the carpenter.


They are blaming the carpenter. They're saying the carpenter is using a dovetail when they sometimes only need a butt joint. Of course there are cases when a butt joint is stupid, but using a dovetail everywhere is also stupid.


server side rendering and progressive enhancement is still be best approach for the vast majority of apps.


Disclaimer: I'm working on ROBOAMP (an AMP generator)

>AMP, loading megabytes of Javascript, claiming to speed up the web?

Of course this doesn't make sense when your content is only text, but this is quite unfair comment about AMP as a whole.


I've gone through the same experience this year, having picked up modern JavaScript, Angular2, TypeScript and RxJS for a project.

For me it was TypeScript that did it. I came to appreciate strong typing. And ES6, fixing the 'this' scope problems and with a conventional class syntax (I understand prototype inheritance is clever, but it's not the way I've been trained to think). I didn't get to use async/await for various reasons, but that looks to remove my third pain point (callback hell/promises/observables).

RxJS remains a mystery (I swear the API wasn't designed for humans) I use and hope it works, and combining code that use Observables with those that use Promises still wakes me up in a cold sweat.

But now going back to old territory (PHP, Symfony) I miss it. Yesterday's miss was union types. TypeScript has spoiled me.


I left React for Angular 4 this year, because I came to the realization that once I made the decision to leave the loosie-goosie world of default JS, there was no reason to have my framework be loose either.

I'm really loving the confines of a "one way to do it" framework like Angular 4. It makes teamwork much easier, speeds up development once you've gotten over the learning curve, and is damned impressive when it comes to app performance.

I'm really looking forward to the day when TypeScript platforms like Angular 4 compile down to WebAssembly and performance goes through the roof.


> I'm really looking forward to the day when TypeScript platforms like Angular 4 compile down to WebAssembly and performance goes through the roof.

You will be disappointed https://github.com/WebAssembly/design/issues/219


> We have spoken with the TypeScript team about this possibility and they have shown interest, but it seems like progress there is currently gated on adding typed objects into JS.

Once JS has typed objects, I think it can become as much of a valid compiled language as anything else. I'm still holding out hope.


Sorry to be a party pooper again, but https://esdiscuss.org/topic/es8-proposal-optional-static-typ... and https://ecmascript-daily.github.io/pages/status-of-static-ty... ... I'd like to see that myself, but what can you do... I'm learning Rust instead to use this in wasm. With new webpack initiative https://medium.com/webpack/webpack-awarded-125-000-from-moss... it's looking good.


> I'm really loving the confines of a "one way to do it" framework like Angular 4. It makes teamwork much easier, speeds up development once you've gotten over the learning curve, and is damned impressive when it comes to app performance.

I found thinking about apps easier in Angular too, being that bit more of a conventional system (for want of a better term) than React. Decomposing everything into a component (as I should in React) is a new skill, and will take some thought for me to get right. I started sketching it out for a personal project and went with VueJS so I could get it done quickly.

mobx fascinates me and I will be trying that - with Angular, with React, with anything it goes with.


how well does Angular perform on production?

as far as i know, React is used more widespread


We used Angular inside Ionic for an iOS app. Performance is OK, but I can't tell you if a different JS framework would be faster, or if it's a device/Ionic limitation. The main problem has been with rendering large sets of data (say 100+ items) in a scrolling list.


It's blazing fast. IMO React is more widely adopted, because it's been production ready for longer and because of the whole Angular PR debacle.

Once the platform development settles down (v2 -> v4 anyone?), I think it'll be the clear option for enterprise level development.


horribly.


TypeScript also works wonders in React. Using a component that someone else made? TypeScript will make sure you are passing it the props it expects. Change the expected props for a component? TypeScript will immediately let you know what code you need to change for every component that uses that component.

Also NoImplicitAny and StrictNullChecks are two great tastes that taste great together. Everything in your code is now typed, AND TypeScript will now actually make you think about how you are handling (or not handling) null values. These two flags have basically allowed us to completely eliminate all the 'X is not a function of Y' and 'Z is undefined in this' errors - which is pretty amazing because for me at least these were probably the most common JS errors I get.


There is no callback hell if you're using promises correctly. While await is the best option, plain promises are pleasant to work with as well. Could you paste an example of how do you use them? If you're actually using them wrong, I'll gladly show you how to do it right.


Think he was trying to say that he likes neither callback hell nor promises


Oh, I didn't get that. If that's the case, I'm sorry for misunderstanding.


Amen for typescript. With TsLint and all the options on JavaScript is almost pleasant to work with.


Most of my projects I wound up switching from RxJS to xstream [1], for several reasons related to size/performance and synergy with a framework I heavily use (Cycle.js). It's RxJS influenced, but written from scratch in Typescript with a much simpler API surface and somewhat easier to reason with semantics (default "hot" and "shared" Observables versus default "cold" and "unpublished" Observables).

Also, Typescript now supports (since 2.3) downleveling async/await all the way to ES5, which is very handy.

[1] http://staltz.com/xstream/


Typescript will give you compile-time type checking, but the actual runtime (javascript) is weakly typed.

For me this is the main problem with the language, otherwise it is a good language even without compile time type checking.


> Typescript will give you compile-time type checking, but the actual runtime (javascript) is weakly typed.

Yes and this sucks. There have been a few bugs I've had (can't remember details) where the types or visibility looked OK in the editor but I was bitten at runtime.

No doubt due to my loose configuration - tightening up the linter would help and getting rid of null/undefined overlaps is my next move.


It looks like the author didn't mention the main reason many of us hate Javascript: weak typing.

Weak typing is great for small-scoped project without a lot of business logic. But when there's a lot of data, a lot of assumptions about it, and, most importantly, these assumptions change A LOT during development - which happens all the time in game development, for example - strong typing is a godsend.

When I make a change in a strong-typed language, I deliberately make it in such a way that the code won't compile unless I complete it. If I can make something a compile-time instead of a run-time error, I do it (and that's why I dream of switching to Rust one day - on some game engine two generations from now, unfortunately). When I refactor something, I know that compiler will let me know if I forget to change it somewhere.

Compiler is my dearest friend. Compilation errors are his gentle hints that make my code better and prepare it from failing in user's hands. Without it, I feel lost and always on my toes. I have to write tests instead. I have to launch the project (which, when it uses a lot of resources, always has overhead) and test everything by hand. When I write a big project in Javascript, I feel like a minefield, unsure of what's broken and what's not.

I can't understand how people write serious, big projects in weak-typed languages.


Me neither. It just seems really fragile and unwise.

I've had people tell me that tests deal with all the issues I would fix with a decent type system, but this seems to involve writing tests to see if things are passing the right types around, which is code the compiler of any strongly typed language already has in it that you don't have to write.

I don't even find dynamic languages faster to get started with, but maybe that's because I'm so used to static ones with good type systems. If you can call C#'s type system "good", that is. It's mostly adequate!


I was a Python developer for about 10 years before joining a startup that works almost exclusively in Javascript. I had to swallow my pride and make the best of it. I had a huge, smug chip in my shoulder.

ES6 has made the language tolerable. Enjoyable even. It has even been a decent medium for mentoring more junior developers who haven't had any exposure to functional programming in school. I can show them combinators, functors, applicatives without all of the usual ceremony in a more pure language. For that JS has been quite nice.

However for my own projects I just use GHCJS or Bucklescript and compile down to JS. Google Closure and Webpack are fine tools for shaking out the unused code and bundling everything up.


Current Python dev here. I've found the same thing. I really didn't like Javascript prior to using ES6. Now it's fairly tolerable. I'm currently building an app with a React based front end and a Flask-based API for data exploration and QAQC.

The "where does the semi-colon go" game is really annoying, but I'm getting better at it, and ESLint will let me know when I mess up. But I do enjoy a lot of the features in ES6 that make JS (EcmaScript will never sound right to me) nicer to write.

My huge pet peeve is that it feels like it takes so much work to set up an app compared to my experience in Python. But maybe that's tooling. I do have some boiler-plate code to get things working, such as setup.py templates and YouCompleteMe for code completion, and I use VirtualEnv and Pip to manage dependencies. I guess that's basically Webpack and NPM and package.json/webpack.config in JS development.

Who knows. My issues with JS/ES might be all in my head.


I'm one of those people that just trusts ASI. Once you stop inserting them you stop noticing so much.

After introducing an ESLint configuration to my team I still can't get the semi-colon lovers to consistently insert semi-colons. I made semi-colons a warning only just to see since ASI will insert them anyway. The worst offenders are the die-hards.

I was originally a semi-colon person but that's only because I listened to a talk by Crockford once and never thought to draw my own opinion. As a Python programmer I thought semi-colons were silly already and this talk only entrenched the unfounded idea that Javascript was bad in my mind.

I use them at work because when in Rome... but in my own projects there's no need for them.

Currying is a nice effect of the fat-arrow syntax for lambdas. Currying in JS is still neutered compared to OCaml or Haskell where it's the default but it's still nice. Function composition is greatly enhanced by it. Python requires special help to do currying.

As for tooling... it's the same deal in many languages despite all of the marketing. It might feel painful to get a good development environment set up for a Javascript project but it can be equally painful to setup a Python environment if you haven't done it before (or a .Net, Java, etc, etc). I'm not a huge fan of excessive configuration. But that's what you get with programmers. We're a fickle bunch.

What Python does well though is to absorb good ideas into the implementation. Function decorators, iterators, and soon mypy; when you go with the grain, Python is a wonderful language.


I disliked JavaScript, but then I read JavaScript: The Good Parts, and I saw that with a bit of discipline* there's something quite pleasant underneath. It's a book that, rather than being focussed on telling you what not to use, instead shows you various approaches to programming with what you should use. If nothing else it'll give you food for thought and unlearn you of your worst beginner habits. Mind you, it's a dated book and ES6 added a lot to the language.

*don't listen to every suggestion of Crockford though; e.g. having to hoist your variable declarations is as obnoxious an idea in JavaScript as it is in C


JavaScript in and of itself is just another little DSL, if you want to do sane things it rows your boat. What creates all the trouble is what people are trying to extract out of it and the usually inexpert community around the language (little amount of actual CS people). It would've been way easier if around 2007-2010 we added a new language to the browser, and had some standards for the average JS programmer. I haven't tried Dart at all, but if Google actually shipped it in Chrome, then others would have to follow. We'd all call them evil for that, but at the end we'd have all others follow and end up with (probably) a proper language to code in for the browser (well my actual thoughts about running that sort of code is rather unpopular and negative, but I'll keep it to myself here to not annoy anybody).


Bingo.

I usually find the people that complain the loudest about JS have been burned by their own ignorance.

I'll admit the learning curve for basic JS syntax can be a little high, but reading through and understanding most of Crockford's book will get you 80-90% of the way there. The rest is either ES2015 or framework-specific -- both of which build off of basic JS.

A good software developer learns constantly.


How is hoisting your variables obnoxious?


It mixes implementation concerns with functional concerns.

He recommends hoisting the declarations because that's how `var` scope works in JavaScript. Normally you'd want to introduce variables where they're actually used to provide context for them.

A variable definition at the beginning of a function implies the variable is important to understand the general flow of the function. This can be especially misleading for temporary variables like counters which only matter within a particular loop.

Additionally assigning values halfway into the function implies they had different values before, leading you to go back and check whether they were assigned anything else (and used for anything else) or just declared without a value.

Of course these problems can be avoided by simply using the new let/const variables which are block scoped, but even here Crockford would likely advocated for hoisting within the same block because of the Temporal Dead Zone (i.e. a block scoped variable exists from the start of the block but referencing it before it was declared is an error).


This is in line with his philosophy to eliminate things that produce little or insignificant value but is a potential source of bugs. In this case variable hoisting.

Of course you don't have to follow all his rules of what are good/bad parts, some of which feel a bit Byzantine at times, but he has a point and usually for a very good reason.

Check out the JsLint Google+ page for his views on more recent additions


Definition and initialisation/usage get separated, which impairs code readability.


Meh, all I got from this article is that this guy is writing a calendar app.

Perhaps that's the whole point of this post. ;)


Yes, but I thought it was pretty funny, so I forgive him his little commmercial.

Anyway, I doubt there's room in the world for yet another calendar app... so I also want to give him a break because I feel bad about him likely wasting his time.


Same here. Very clickbaity title. "I like JavaScript now" is basically a TLDR version of the post.

More

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

Search: