Remove the browser practical monopoly, and JS popularity would vanish.
Also, languages are always a function of their ecosystems. You could argue, remove Apple products and Swift/ObjC would vanish.
Easy to reason about, great performance for most cases, simple to debug and write code for, a plethora of libraries, easy to ship, no need to have different teams for backend/frontend, and minimal tooling needed.
GP comment was presented somewhat snarkily, but I'm not sure they're all that wrong.
But I have yet to find a language that has the same set of features except JS. If you want to offer up an alternative, please do so.
There is not a single feature in JS you can't find elsewhere, often better implemented.
If anything, the vast majority of scripting languages (Python, Ruby, PHP...) have more features than JS.
JS is so lacking in features that half of its ecosystem is dedicated to compensate for that (typescript, babel, webpack, undersacore...).
Yet one feature does not a language make. A language is the whole of it's behavior, and JS is a perfectly fine solution with a wide mix of good features.
Is it the fastest? No. The most performant? Not close. Does it have the best ability to write language parsers? No!
But it's not supposed to. It's a general purpose language that's well suited for a wide swath of cases.
Most languages have transpilers and utility libraries - and those are useful tools but also not meant to be part of a language. Even python has dozens of compilation tools depending on how you intend to distribute your code.
It's the mark of a poor intelligence that buys on pros only without considering cons. We must weigh not only our features but how well the average engineer can use it, how quickly we can produce features and how safe our code is, and how easily we can actually hire and train engineers.
JS is one of the most popular languages in the world. My 10 year old nephew can write it and do a decent job of it.
JS is a fine language. It doesn't really bring anything new/different to the table (other than prototype inheritance, but that doesn't amount to much IMO), so the real differentiating factor is that it has a privileged position because of browsers.
Very dishonest take btw.
Here's a forum of people who could tell you why they use JS instead of your $favelang, yet instead of trying to figure it out, you just assume everyone is lazy or a junior dev except for you.
You should be a little more suspicious of convenient little truths like that where you're the cool elite engineer protagonist and everyone else is a bumbling idiot.
I use JS on the server. Any questions for me?
I also didn't say everyone is lazy. I said a lot of developers.
Most people here do not belong to that use-case. As they are mostly here by interest and are willing to learn.
But most people, after work, don't do anything with their knowledge.
And are more willing to learn node as it's the same on the backend + frontend.
Or keep using what they already know, with no interest for other languages.
So for the rare cases where async does matter (and they are a niche, given even big names like facebook code behind async proxy and do long polling), there are still little reason to choose JS.
I can't think of a single mission where, if I were not being forced to use it, I would chose it over something else. And I say that while coding a LOT of JS all year long. Even training people regularly in the language.
I double down on my initial statement, if tomorrow JS is removed from the browser, it would die in a few years.
It's a badly designed language that has been accumulated fixes over the years to make it acceptable while never removing what's bad. It was so initially bad that half the ecosystem of JS exists to not code in JS (typescript, coffeescript, babel, jsx, webpack...).
And it has received that much of attention because we had no choice. Google spent millions to make a technical marvel of a JIT to run it at decent speed.
Any tech that would have had half the resources poured into it would today be the incarnation of skynet.
It's a language surviving on artificial life support than can do so because it has the best blackmail game of all time.
Java?
The JVM is one of the most amazing piece of tech ever created. It's so good it supports not only what has been most the popular language in the world for years, but many newly popular languages like Kotlin or Closure. The perf have been optimized so much they are getting about 70% of C/C++, but with high level paradigms. It can pretty much do everything.
In fact, it runs on everything. It used to run on old school nokia phones. It runs on some credit cards! Despite being slowed down by patent trolling, Java found its way to more than half the modern mobile phones in the world throught Dalvik reimplementation.
It's everywhere.
Today, it is still ranking #2 on TIOBE and PYPL, despite having to leave with 2 decades of legacy design decisions and no monopoly.
You don't think JS is obviously unique for its ubiquitous Promise, async/await, + async-everything abstraction. You tend to only get that in other languages (Rust, Python, Ruby) by limiting yourself to a fraction of the ecosystem.
Btw, what's lazy is making convenient uncharitable assumptions about others than just... asking.
This forum is full of people who could tell you why they still use JS after they analyze pros/cons of other languages.
You are here because you are interested and want to learn. You probably know more than 1 language.
But that is not the general developer. Most developers are lazy and at the end of the day, want to go back to their wife and kids ( for example).
The real problem is that businesses don't want to train devs in the right tools for the jobs at hand, and are instead looking for the shortcut that will let them 'ship it'.
I agree, never claimed otherwise.
> You don't think JS is obviously unique for its ubiquitous Promise, async/await, + async-everything abstraction. You tend to only get that in other languages (Rust, Python, Ruby) by limiting yourself to a fraction of the ecosystem.
A fraction like nodejs or whatever subset of NPM you decide to use?
Core JS is what you get in a browser. That includes async/await, but it's hardly ubiquitous in usage in the core.
The main distinction JS has over Perl, Python, Ruby etc is that it's in the browser, so you can assume almost everyone has it and it's accessible in some manner if they access a web property you are responsible for.
I'd like to know what language you use as a baseline for this?
I made my first "real" Javascript code back in 2005 (a vector map system that worked in realtime) and I've been working mostly with frontend for the last 3 years so it is not lack of familiarity. In between that however I have programmed a lot of other languages, worked in a number of different teams, written new code, maintained old code and generally gotten some perspective on life.
That perspective has sent Javascript down my list of languages that are easy to reason about.
The lack of OO means no typecasting, inheritance models, interfaces, etc.
Arrays are fully dynamic, not type restricted and operate strictly by reference.
No memory mapping, manual garbage collection or even GC adjustments.
Suddenly the list of things someone has to understand to be a competent JS engineer is way smaller than a language like C or Java.
There are other languages that have a similar level of being easy to understand such as Python and Ruby, and they're good languages too but have a different set of tradeoffs.
Here's my attempt to create something similar from my perspective:
- Being able to know to at any point what a variable can contain is very liberating. (Ok, you can define a list of Object that behaves just like a list in JS: "fully dynamic, not type restricted", but thankfully for people like me that is not common in Java anymore.)
- Knowing that the compiler has my back allows me to work faster.
- My preferred languages (Java, C#, TypeScript) together with version control allows me to refactor fearlessly.
+ An engineer had written a script with a Dictionary of type <Transform, Material>. If you've touched Unity, you immediately caught the flaw: Transform's aren't unique enough keys and it's really easy to end up trying to add Duplicate keys, even though you really mean different objects.
+ So, since we don't care about uniqueness, shift from a Dictionary to a List. Except we have a problem, because we need to keep that Key->Value relation so we know what transforms get what materials. Well, we have a solution to that, it's yet-another-type called a KeyValuePair.
+ Well we're now nesting a generic KeyValuePair that needs type information inside of a list that is holding <KeyValuePair> objects, which also changes how we iterate through that list and add items to it.
+ In a language like JS, everything I just said doesn't matter at all because instead of using a Dictionary (Map in JS), we would of just said "Use a Set instead". Done.
If they started using PHP, without monopoly, they would not have switched to JS.
But plenty of people have switched from PHP to python or ruby.
> Also, languages are always a function of their ecosystems. You could argue, remove Apple products and Swift/ObjC would vanish.
Python, C and Java are not.
Right now, you have options to avoid writing js at all. There might be some glue code in js but you can write vast majority of your code in other languages and target js. People still choose to write in js.
Purescript, elm, clojurescript, kotlin, bucklescript, and the list goes on. There is a to-js transpiler for every popular language. Why aren't they seeing more usage?
So i don't subscribe to idea that js is not popular because of browser monopoly.
Because a layer of indirection is a heavy price to pay.
If I could code in Python with zero cost in the browser, I would. Hell, I would code in Lua, Lisp or Ruby if that was the alternative.
There are also huge classes of bugs that exist in these projects that a statically typed language completely eliminates!
If they're running into trouble from having to have types, it's almost certainly design and architecture issue and does not make me think that deno is going to be a solid project.
Strong typing is from OOPS, itself an optional programming methodology. There are many JS programs that simply access other (JSON) objects directly without going through an interface. In these instances, typing is counterproductive.
One of the beautiful things about JS (and Lisp) is that variables and functions are interchangeable and, the case of JS, both can be accessed directly without worrying about an interface.
At the end of the day those type exist in JavaScript. If you access ‘first_name’ instead of ‘firstname’ it will not work. The difference is that typescript would let you know before running the code instead of getting an obscure runtime error.
I'm honestly wondering: What are people doing to end up in a position where TypeScript compile times are a problem?
If they dropped use of classes, or differentiated the names of the two things in collision the problem would appear to be solved.
To turn that around and blame TypeScript as the point of failure is an extremely bad omen suggesting their code style opinions are more important than product delivery. I could live with that nonsense if this were a framework or some minor dependency, which this application is not.
Edit for the curious, here's the monster type that caused such pathological build times...
type ImmutablePrimitive = undefined | null | boolean | string | number | Function;
export type Immutable<T> =
T extends ImmutablePrimitive ? T :
T extends [infer U] ? readonly [Immutable<U>] :
T extends [infer U, infer V] ? readonly [Immutable<U>, Immutable<V>] :
T extends [infer U, infer V, infer X] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>] :
T extends [infer U, infer V, infer X, infer Y] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>] :
T extends [infer U, infer V, infer X, infer Y, infer Z] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>, Immutable<Z>] :
T extends readonly [infer U] ? readonly [Immutable<U>] :
T extends readonly [infer U, infer V] ? readonly [Immutable<U>, Immutable<V>] :
T extends readonly [infer U, infer V, infer X] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>] :
T extends readonly [infer U, infer V, infer X, infer Y] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>] :
T extends readonly [infer U, infer V, infer X, infer Y, infer Z] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>, Immutable<Z>] :
T extends Array<infer U> ? ImmutableArray<U> :
T extends ReadonlyArray<infer U> ? ImmutableArray<U> :
T extends Map<infer K, infer V> ? ImmutableMap<K, V> :
T extends ReadonlyMap<infer K, infer V> ? ImmutableMap<K, V> :
T extends Set<infer M> ? ImmutableSet<M> :
T extends ReadonlySet<infer M> ? ImmutableSet<M> :
ImmutableObject<T>;
type ImmutableArray<T> = ReadonlyArray<Immutable<T>>;
type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>;
type ImmutableSet<T> = ReadonlySet<Immutable<T>>;
type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };So, instead of waiting a minute for the typescript compiler, you wait for the engineer to write tests.
Firstly, they'd be written in the same language that you are coding in, not a weird, half baked type language, that adds visual noise to your code.
Secondly, they'd have much more power to define meaningful and useful behaviour rather than being restricted to talk about correct behaviour via types.
Thirdly, they'd run when you wanted the tests to run, and you could tier different tests to run at different times, so they aren't all slowing you down while you're doing fast iteration.
I used to like types, but then I realised that what matters is how quickly you see the bug. Seeing it in your code editor is brilliant, but if it's slower in time than hitting control S and seeing the actual app in the other pane auto reload, and fail or not, then it's worse.
These days I look on the idea that you know the exact types of all data your program will interact with at the time you write your code as the same sort of mistake that we made when we thought we understood the deep inheritance hierarchies of the real world.
I write a lot of Purescript and a lot of Clojure. Purescript, being basically a Haskell variant, is about closing down every last little part of the system into types. You _do_ pick up a lot of visual noise for this (like `liftEffect` ugh...). Whereas Clojure, is the polar opposite. It's about keeping the system open, using large chunks of data, and having functions take/change what they need and pass along everything else none-the-wiser to what's present.
Bouncing back and forth between these two worlds, I think I've begun to lean towards the opinion that I really only care about strict types at the boundaries of my program and certain very specific checkpoints along the way (generally, something like a module/namespace boundary).
Clojure has Spec, but it misses the mark in my opinion because it doesn't solve refactoring. It's not (currently) instrumented enough to help the me as a human make changes to the code without also just "bumping into the guard rails" to try and figure out what I broke along the way.
A middle ground orthogonal type system sounds really appealing to me. "Type coverage" is an idea I've been kicking around. Something like Spec in Clojure, but more symbiotic with the host code such that it can tell you things _about_ your code and help in refactoring, symbol resolution, etc..
That's a lot of words, but tl;dr I think I agree with you : )
It's quite obvious that there are downsides to types that most developers are missing - because most developers seem to feel that they get massive benefit from types, but empirical studies seem to show that if there really are benefits, they are not massive.
I see the downsides in a few ways - they open up another avenue for 'architecture astronauting', they are not in fact accurate representations of the real world in many situations - you're dealing with files, or messages coming in from the network which are not typed, and even when they are (e.g. databases), they can change under your code while you're running. That's not to mention the points I made above around usually being an entirely different, hobbled language that gets sprinkled through your source code. Types encourage people to build ridiculous code generation pipelines during build time, and builds getting larger and flakier are about the worst thing in the world for fast iteration. I find the Smalltalk approach of coding in a live image really interesting, and I worry that obsession with types are closing off that kind of future. There's also the fact that your language, and particularly your type system constrains what code you write - like a programming version of Sapir Whorf, and most type systems are bad at expressing very high levels of abstraction. Scala had to invent a documentation tool that hid the real types of things because the type signature of higher order functions like map and reduce were scaring people.
I was interested in your opinion of Spec, because I'm aware of it and find it interesting, but I don't do a lot of Clojure so I haven't really used it practically. I liked that it aimed to address more than just verification - schemas, object generation for property testing, these things are all closely related to the general concept.
I think your ideas about a middle ground type system seem very interesting.
I saw recently that there's a version of Nim 'DrNim' that incorporates the Z3 theorem prover which allows you to assert and prove much more interesting things than typical type systems. It sounds fascinating.
Which, if we're doing TDD, involves no waiting at all, since it was already written before the implementation. Ideally anyway.
Type safety is easy in a dynamic language. Stop mutating variables and stop mixing types. Suddenly that whole class of errors evaporates. No need to test things that are impossible.
And for those times you want some magic in your life, nothing is stopping you, no need for generics, just proceed with caution and test accordingly.
Lisp programmers use check-type[1] a lot, they proclaim[2] types for performance optimizations and they often deftype[3] if not only for code clarity. And then we have CLOS and its dispatching on types/classes...
[1] http://www.lispworks.com/documentation/HyperSpec/Body/m_chec... [2] http://www.lispworks.com/documentation/HyperSpec/Body/f_proc... [3] http://www.lispworks.com/documentation/HyperSpec/Body/m_deft...
I object, C is that.