It's important to understand that, by virtue of having been bestowed with a monopoly over the web, JavaScript holds a great deal of leverage as a language. If you want to develop for the web, you pretty much have to adopt JavaScript into your stack. It's no surprise, then, that Node became so popular. Being able to use that language you're forced to use for the client on the server and to run the same code has major benefits. The Node and npm developers got many things right to be sure. But Node and its ecosystem, by virtue of offering JavaScript, benefitted immensely from developers' desire to unify a previously disjoint part of their stack.
I find myself asking instead, how far will JavaScript's reach continue to stretch? Electron and React Native have become extremely popular. It's not just speculation, there is undeniable momentum.
Now when I want to use a JS library, I have to think: what is this author's philosophy about language extension? Are they going to start using some new feature that some other library I depend on is incompatible with?
You used to be able to run JavaScript anywhere on any device. Think about how powerful that is. We sacrificed that for supposed gains in "ergonomics".
People hate callbacks. People hate "this". But if you ask people who really learned how to use those things, they're not problems at all. They're only problems if you're coming from Ruby.
It's like someone took an Apple and said "this is gross, it's not juicy and tangy like an orange!" And then they soaked it in vinegar and wrapped in orange skins. Now it scores well on orange-ness but is that a virtue?
Yea, but that means if I want to use your library, I need a build chain. It used to be I could just do require("you") or <script src="you"> and be done with it. That's what we lost.
Actually I need n buildchains, one for each npm module I use. And they better all be compatible and target at least one common runtime. And that better be a runtime I am comfortable deploying for my app.
> I've also literally never met anyone who thinks that callback-structured code is "not a problem"
Well here I am. Pleased to meet you. Might I also point you at: http://callbackhell.com There are many of us.
I think what this really shows is how much professional ES6 programmers live in a filter bubble.
This also explains why you think "just transpile" is a reasonable substitute for a simple, run-anywhere language. Professional ES6 programmers think everyone has 40 hours a week of paid time to spend maintaining a build chain.
Javascript+Node used to be one of few languages that you could use without a build system. That's no longer the case. Maybe the loss was worth it to you. Fine. Makes sense. I wish more people would just acknowledge something has been lost, and that amateurs are struggling now at the expense of pros.
...aren't ES6 and ES2015 the same thing?
The minute you decide to transpile, you no longer really using javascript, and this discussion isn't really relevant any more.
That said, I still feel that not sending the event registration context (not just the target) in with the event is a mistake... escalated by the use of fat-arrow functions today. You never know where things will go.
As to callbacks, I think it provides a great base... allows for easy extension and progression. I do now prefer Promises where async/await is available or via babel.
Java 8 isn't the same as Java 3... it's changed... languages evolve, and JS has done so rather rapidly the past 6+ years... It looks to be settling in a bit now. Next will be the module support, and that shift will be more painful than everything that came before.
I don't mind the context class sugar... there are places where it makes sense, and far cleaner than the prototype syntax. I tend to only use it for UI components, and even then sparingly. Just the same, other parts of ES6+ have been incredibly great.
The very fact that you need to learn to work with X means that it's a problem. Otherwise, all languages are just fine.
Some things are stupid even after you understand them, and JS has plenty of those, as its creator and its greater evangelizer both admitted.
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+ [])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()Seriously, it is not a good reason. Just don't write code like this nor allow other people in your team to write code like this. Fortunately, this kind of code is unlikely to be written by mistake so it is easily avoidable.
As for team, in enterprise consulting, the concept of team is very shallow.
I don't think it's that productive to judge a language on the worst features and edge cases that most teams will be able to easily reach consensus on avoiding, as every language will have its bullshit.
Only those edge cases merely expose functionality that can burn programmers on an everyday basis, like coercion rules.
It's not something that you have to get out of your way to get.
You do know there are many, many languages where that sort of obfuscation lay between difficult to impossible, right?
It's just a side-product of JS god-broken coercion rules and types, and those affect every statement one writes, down to the suggestion to use === instead of == for the most fundamental thing any language does: equality comparison.
The example is just meant to showcase how far the brokeness can be taken...
I tend to favor the mantra of be a liberal when consuming data and a conservative when exporting data and I find the == vs === does that very well. Sure it's a gotcha but no big surprise to most people that have been doing JS for any amount of time. I personally think it is a brilliant feature that save a lot of boilerplate when one understands the difference.
I don't think this is true at all. I think over time it becomes very easy to apologize for the environment we're forced to use, because there is no comparison, we only have JS for the web.
In any decent project, you're going to have hundreds of 3rd party dependencies installed from tons of sources, some of which could freely introduce exploits into popular programs at any time. If any of these break, you're going on a long hunt to track it down, ultimately to be met with authors that aren't responsive or some bug caused by god knows what incompatability.
We're stuck between the ever flowing battle of new language constructs and languages ontop of JS that try to make it 'easier'. JS lacks very important things that devs have found to be necessary, like typings, and even trying to add typings is a huge battle in itself, that again, is ever changing. Just try and google for where you should put your .d.ts files, and you'l get 4 different answers, all from different stages of versions and recommendations.
You can't teach JS. You can only say that things never stay the same, so build things fast and break them quicker. What you consider 'properly' today, is tomorrows bad practice.
One of those 'it takes a village' to make a good JS app.
I'm kind of disappointed with the introduction of the 'class' keyword though (and the way it was implemented). The old prototype function declaration approach is really good once you understand it.
I'm sorry, but how does a seasoned Javascript developer ignores the absence of compile-time type checks? Aside from switching to a language that compiles to Javascript.
If I needed compile time type checks for a snippet of code, I would use a language with compile time type checking that compiles to JavaScript.
If I needed compile time type checks for many snippets of code, I would take a few days off and rethink my architecture. Ask myself why my call sites are so brittle or confusing that I am making frequent type errors.
Why is it suddenly a foregone conclusion that seasoned Javascript developers all want compiled statically typed languages?
Please argue with me, because I _want_ to be convinced. I'm trying.
It may be because of the habits I developed, writing compiled code. I always would first concentrate on my concepts, things that I want the code to do, data and flow structure - while keeping all errors (even syntax) silent. And only when I got everything I wanted implemented and consistent, I would turn to a compiler to quickly fix all mismatches in API, all wrong method names and other trivial blunders.
Now I stumble, feeling that I'm a blind man going through a minefield. Every line I write, I have to think about the things that I want to express and the mechanics of language and API simultaneously - because nothing's got my back. (Yes, I know that I should write unit tests, but not all of us have the luxury of working on perfect projects, starting perfect projects from scratch, or having the resources of putting good practices into legacy code).
Every time I discover that I mistyped the name of the function or variable, forgot to use "this" when referring to an object property (C# habit), forgot that external API function returns a custom type and not a string - I do it too late. Instead of quickly fixing the thing that I've only typed right now, I have to go back, and spend time reading and understanding relevant code again.
All I'm trying to understand is, where are the trade-offs? Where are all the awesome dynamic things that make all that worth it?
Now, if you're writing a programming language, this probably seems pretty awesome...
Type Checking vs. Metaprogramming: http://www.oilshell.org/blog/2016/12/05.html
http://www.oilshell.org/blog/2017/01/21.html (at the end, pretty printing requires metaprogramming, or escaping into another language)
Whenever you have a code generator like an ORM, or protobuf-like schema languages, you can use metaprogramming instead. Generally I think this helps the program so you don't have these impenetrable walls between layers, where one person understands one side and the other person understands the other.
I find that a lot of programmers coming from statically typed languages are writing Java in Python, or Java in JavaScript. In Java you don't really think in terms of metaprogramming.
If that's the case, then it is going to feel annoying. You're getting all the downsides without any of the upsides.
I would look at Go for other examples of the downsides -- namely the lack of generics. Go is attracting a lot of Python and Ruby programmers.
In Go, you can't write basic generic functions like max(), map(), filter(), and sort() -- in JavaScript and other dynamic languages this is not something you would think twice about.
I guess between metaprogramming and generics, dynamic languages let you write more abstract and concise programs. Programming in statically typed languages feels repetitive to me, and the architecture is quite clunky unless you are doing textual code generation.
Steve Yegge also has a bunch of good posts about dynamic languages.
Thanks for the honest question. I think it's important to remember that there are tradeoffs. I fully admit that type checking is useful in many circumstances. I would like the best of both worlds. I'm a little disappointed that recent hybrid languages like Dart and to some extent Racket have had problems with optional typing and gradual typing. It is something I'm interested in but it seems like an unsolved problem.
Thanks for "When Polymorphism Fails" link, it was a wonderful read. I've actually run into such situations a couple of times - but in my experience, you want most of your methods to be statically checked, and only a minority of them to be added and checked dynamically in runtime. May be the solution is to have two different method tables, that look and behave in a different way?
However I will point out that probably 80% of the world's top websites are written in dynamic languages -- Wikipedia, Facebook, Yahoo, YouTube, Reddit, etc. (that's not even counting the JavaScript.)
So there is something about that use case and dynamic languages... That's not to say a language is great because it's used widely. But it means that it must be getting something right, and not doing other things too badly.
So yeah all I'm saying is that there's a tradeoff. If there's was no tradeoff, then it would have never have swung toward dynamic languages in the 90's/2000's. It's not like we didn't have statically typed languages before the web. But things swung that way, and it sounds like they're swinging back, with PHP, Python, and JavaScript all getting optional types in one way or another.
The language is constantly being improved while maintaining backwards compatibility. Finally it's ability to handle whatever kind of data you throw at it until you choose to check the data is a strength in an environment (web pages) where nothing is certain. You aren't sure about the data you will get from an API, from the user, you don't even know what kind of environment your code will be run in! The same code might run on the latest version of Chrome, a headless test environment, or some old version of Internet Explorer. And that is totally possible. It's all up to how you code it. And you have to get used to coding in this type of language. You can and should test your code as you go along, no need to wait to compile, you can see the results right away. Build your code to handle errors, because even if the code is perfect, the data you are working with will not be. And have lots of tests. Not only do they identify current errors in the code, but they allow you to make large changes with confidence that everything else is still working like it should.
I jist can't deal with the sloppy wild west way Javascript world works.
I like Javascript, and that's enough for me - and I (in _most_ situations) find dynamic typing more of a benefit than hindrance; but I don't mean to purport that my perspective is everyone's perspective :-) IMO it's very plausible that dynamic typing will never be better for you; because we're all different and we don't all like the same thing. If you've come to learn that dynamic typing doesn't suit you, act accordingly, don't just try to change yourself because something else works for others.
If you're interested in static typing, maybe try moving to Typescript? AFAIU it also integrates fairly well with normal Javascript, and hence maybe it's more to your taste? And if there are other people feeling the same way you are on your projects, it mightn't be too difficult to move new (or maybe a subset of new) development to something more your taste instead? (I've heard good things about Flow as well, and maybe it's simpler to "sneak in" to your projects, and offers big enough benefits for you?)
In my experience, legacy projects (or projects where there's pressure to cut corners (eg unit tests)) are often the bigger issue than the language. (eg I've been "in pain" working with code in languages I otherwise like that was obviously done in a big hurry, or evolved obviously from clumsy requirements and hence has big inconsistencies.
(As an actual example of a reason _that applies to me_, the last Javascript project I worked on ran the integration tests faster than the last compiled statically typed project compiled (and reloaded) - hence I ran the tests in a watching process, and felt more productive and less frustrated. And yeah, I haven't written `this` for a very long time :-p )
For example, it's common to use Flow with Javascript to enable static type checking before actually running it.
The language itself doesn't guarantee type safety, but when used with peripheral tooling, the developer isn't missing too much.
Really, I find compile time checks to be moot when you have fast running and good unit tests.
A by product of testing your logic is that it will fail if there is a type cast problem.
But there is so little structure, and so many roll-your-own efforts, the JS world is heavily fragmented...
> we're too bad at educating people in how to properly use the language
Does such a thing exist? How does a seasoned JS dev avoid DOM manipulation/interference nightmares, lack of typing, event hierarchy complexity? How do you really make a modular site without heavily committing to one framework?
> ideal of a perfect language is a pipe dream
Nothing's perfect, but still keep fighting for better.
And the world keeps spinning.
1 + 'a' = "1a", I've seen more ellegant solutions, I'd love JS to be strongly typed at least (without typescript).
I think instead the real issue is that we're too bad at educating people in how to properly use the language. Sure there's corners of the language that are bad, but as a seasoned JavaScript developer you simply know to ignore those corners. So they don't bother you. You instead focus on the cool things about the language. Any programming language have good and bad things. And we as developers learn to focus and leverage the good parts to our advantage. The ideal of a perfect language is a pipe dream unfortunately - instead my advice is to really learn the language and embrace it instead of fighting it.