Why JavaScript
nicolas.perriault.net
nicolas.perriault.net
Oh, what, you thought == was for comparison? Wrong. Oh, you didn't wrap your all your code in an anonymous, self-calling function? You lose. Oh, what you thought it was okay to leave off semicolons and var statements because they aren't required? Sorry. Hmm, you didn't know how to manage dependencies between scripts? Should have studied harder. You tried to iterate over an array? Ridiculous. Your brain exploded when trying to write a series of asynchronous functions in continuation style? A pity, really.
People who are good at JS like JS because it makes them special. They can lord their knowledge of the quirks over "lesser" developers who come to JS expecting it to act like a sane language. It took an entire industry about a decade just to learn how to tame it. Sure, JS turned out to be really extensible to new paradigms, but hey, so is the lambda calculus.
A good language makes good programming look natural. Like Python. JS is the opposite.
You speak like C syntax is "natural" - I remember grappling with pointers and references, it took some time for me to get it fully. It's not like Python doesn't have it's quirks.
I find it ironic that those who use Python/Ruby/Clojure/etc want to often ridicule those who use JavaScript. They've got their own form of elitism. Get over it, seriously.
0 == false
or even better "0" == false
edit: I should note that I don't think JS is a horrible language or anything, but it does have more than its share of oddities.Incidentally, there are quirks - the worst is with having to define a "that" variable, I guess I just don't see these JavaScript issues as all that terrible. Unlike PHP's type coersion system, Javascript's is quite sensible.
Okay, then. Never mind that essentially no language in widespread use enforces that.
Perhaps my "never" was too strong.
"0" == false and "" == false but "0" != ""
Edit: Or maybe a less defendable example of my point:
"0" == 0 and "" == 0 but "0" != ""
Actually true. And truer to the dynamic spirit of Javascript than ===. Sometimes things don't have to be absolutely equal to be equal, "1" and 1 will do just fine. You can sanitise at another level.
>Oh, you didn't wrap your all your code in an anonymous, self-calling function? You lose.
You loose nothing. You merely expose some names to the global namespace. Which might just be just one name, anyway, sans the anonymous self-calling function. (e.g
window.ns = {}, ns.doSomething = function() ...
>Oh, what you thought it was okay to leave off semicolons and var statements because they aren't required? Sorry.
Sorry for nothing much. A lot of people leave them off with no problem at all. The few edge cases are not unlike any other language's edge cases.
>Hmm, you didn't know how to manage dependencies between scripts? Should have studied harder.
Or not. If you got the result you want.
>You tried to iterate over an array? Ridiculous.
You probably mean the "for i in" idiom. Which is perfectly fine over an array. The only problem arises if someone has extended the Array prototype, which you shouldn't do anyway. And even that can be bypassed with one extra hasOwnProperty check. Not to mention it's solved in ES6.
>Your brain exploded when trying to write a series of asynchronous functions in continuation style? A pity, really.
Well, that's just because Node async style is amateur hour BS, like trying to do closures in C or logic programming in PHP. Doable, but not supported by the language. Use Go or Dart or Haskell or C# or Scala or Tornado etc for your async needs.
If async programming in JavaScript "isn't supported by the language": what good is it, then?
It was designed to be easy to use with callbacks for website UI style events (which is not quite the same as async programming).
The Node async is just a half-thought implementation of async on top of a VM that doesn't really support it. The thing it has going for it is traction (and some people new to async are amused by the callback style and find it "challenging", whatever).
Scala/Dart/Go/Rust/Haskell/etc have a better async story.
ES6 will add some promising stuff in the future (no pun intended).
* If you want an async value you need to give it a name and put it in a callback argument. Instead of `f() + g()` you end up doing `f(function(a){ g(function(b){ ballback(a+b) } ) })`
* You need to explicitly tell the order of execution of everything (as shown in the previous example)
* It can very laborious to refactor a non-CPS subroutine if part of it needs to become async, specially if you have many loops or call other subroutines. Ideally you shouldn't have to do large "boilerplate" rewrites of your code just because of a small local change.
If you are curious what the better alternative for to CPS style is, my opinion is that the way to have the language do the work of breaking the code into the callbacks for you, either via dialects that compile to JS or via features such as generators. While you can get away with many of the very nice async programming libraries out there, they still can't solve all the problems with CPS style (specially the refactoring one)
If JavaScript was a nicer language I would be spending more time in Node.JS, but it's not, so I'm sticking with Rails.
You only really need a "canonical" way to do things if you will be wanting to use features that depend on your classes being implemented in a predictable way. For example, class inheritance or implementing "super" method functionality.
> I haven't even dared to touch trying to use it for polymorphism.
Its not at hard as it sounds, since you have first class functions and closures. You can often handle functions directly instead of needing to create objects for everything.
All those points are moot. It's like pointing C's many flaws (or PHP's myriads). Or Ruby's. Or Javas. All languages have several syntactic or semantic issues.
It didn't "took the industry a decade to learn Javascript". It took the industry a decade to have:
1) Mostly compatible implementation of JS and the DOM. 2) Powerful enough computers and JS VM so it can be used for fancy stuff. 3) A reason to use it (AJAX and involved web apps).
Nothing of which has anything to do with Javascript's "difficulty" or "quirkiness" as a language.
And that being said, most people coming from [name your favorite language] believe that Javascript works the same way as their language. It's a different language and require a different knowledge. In fact, javascript' similarity to algol might be one of the biggest problem of the language. Have you tried working with C++ without learning the language?
And here are some Python cool "features":
def foo(x=[]):
x.append(2)
print x
foo()
foo()
Guess x? To take your term "You lose". print 3/2
What's the result? If you answered 1.5, sorry, you're wrong. We're using Python <2.2 here, and it gives 1.Here's another one, what does it do:
for i in range(10): print "*",
print
Is it ""? Sorry, a comma at the end doesn't include a "\n" but automatically insert a space.Anyhow, have fun here: http://stackoverflow.com/questions/530530/python-2-x-gotchas...
Default list/dictionary arguments are plain evil in Python, no disagreeing there. I've been bitten by something like the following before, which is similar to your snippet:
x = y = []
x.append(2)
print x
print y
As for your other examples: except for Pascal/Delphi, I have never used a language that has separate division operators for floats and integers, so at least for me it's only natural that 3/2 == 1, how else would I do integer division?The print example is just very weak, I can hardly even call it a WTF. Yes it's a little odd, but you're not going to hit weird runtime bugs like when you are comparing things in JavaScript, for example.
I'm frankly very surprised by the almost complete absence of real Python WTF's in the Stack Overflow discussion you linked, I would have expected more. If anything, it actually shows how clean and predictable Python is.
We use it because we must, not because we choose to.
Problem is, compared with other modern commonplace languages such as C#, Python or Scala, JavaScript simply loses on nearly all fronts. These languages all have all the points that the OP lists about Javascript, plus a whole bunch more.
Only when compared to the hot languages of the nineties is JavaScript a serious improvement.
That said, the fact that it's not awesome surely is no reason to diss it. JavaScript does have those Good Parts, and it isn't bad at all. Just not great either.
Still, i can't wait until we can avoid it altogether and consider it some sort of bytecode that those old hackers with mustaches wrote by hand, back in the day. In text editors!
There is plenty of good criticism for C++ out there. I would never use it by choice, but it is almost the only reasonable language to use for game development at the moment.
Java is less insane than C++, but it's also extremely verbose, restrictive and inexpressive. The JVM is also annoying to deal with, in particular because of startup time, memory usage and debugging.
Both have stupid, useless type systems that only get in the way. There is almost no value at all in the kind of static checking either of them does.
While I see the value of a good type system (like Haskell, Scala, Rust and to a small extent Go), I have yet to be comfortable enough with either to replace Python to any extent. I've done "evil" things in Python in a pinch that I'm not sure I could easily reproduce in a non-dynamic language.
There is almost no value at all in the kind of static checking either of them does.
OK that's just ridiculous. If nothing else (and there really is a lot else), they catch undefined variable usage and such.More interesting static checking is not, however, doable in either C++ or Java. Hence why I find that the current checks are not worth having a stupid and annoying type system.
Ecosystem-wise, I guess PHP's is a bit larger, and JS's is a bit smarter, currently. The amount of absolutely horrible JQuery plugins is already paralleling the amount of horrible Joomla extensions; I'm curious to see whether the NodeJS'ers can keep that culture from creeping into their side of the wall.
All in all, pretty comparable.
These libraries all seem to use and encourage different patterns and trying to use 2 together often leads to confusion.
Switching to a project that uses something different, say prototype instead of jQuery feels like learning from scratch again.
Self promotion: I believe the above so firmly I went out and started a school for JS devs, Hack Reactor (formerly Catalyst). http://hackreactor.com
@hackreactor: nice! @packagemanager Yeoman (http://yeoman.io/) does something like this and a couple of other solutions, too.
Could you tell at least one compelling objective reason to do so? Especially for non-web-frontend developers out there?
On the other hand, this was said by the creator of C++ and correlation doesn't imply causality; maybe some of the factors that contribute to a language becoming mainstream also cause irritation.
In the recent time I've often read posts about people suggesting: learn language X to a reasonable proficiency before you criticize.
This is part of the reason why languages like CoffeeScript and TypeScript have become popular. They offer the tools that developers actually need, rather than just telling them, "you should be using prototype-based OO because it's good".
The proper way to do inheritance in JS is
// Foo extends Bar
Foo.prototype = Object.create(Bar.prototype);
function Foo() {
Bar.call(this);
}
Before the introduction of Object.create, you either had to roll your own version, assigned a dummy instance of Bar to Foo.prototype (which is horribly wrong) or transferred methods manually from Bar.prototype to Foo.prototype, which is arguably more 'in the spirit' of JS1.0.That's not how it's done in 'real' prototypal languages like Self or Io.
It doesnt make javascript a good language , in fact it is not. It is a poorly designed language that should not have survived the 90's, and if it would have been invented today it would have been different beast. Is there some good stuff in it ? sure, but the irony is it is used to code against the DOM which is strictly typed and made of classes and interfaces( that's the why of DHTML , because it made no sense to use that language against that API ).
Now People can rant about it all they want it wont make a difference , browser scripting = doing some javascript , wether one likes it or not.
These people also usually have many years of experience with other, far more sensible programming languages, too. I'm not talking about PHP or Ruby, either. Rather, these people know one or more of languages like C, C++, Objective-C, Java, C#, Haskell, Erlang, OCaml, Standard ML or Python inside and out.
With such knowledge, it becomes very obvious just how bad JavaScript is. The utter stupidity of many of its flaws becomes so apparent. These people also can see how it lacks the language features necessary for large-scale, multi-developer, distributed development, and then the subsequent maintenance of such projects. They've felt the pain of its numerous other problems time and time again.
I'd say the reality is much the opposite to what you describe. The ones who advocate JavaScript most often have never used anything else. They don't realize how many of JavaScript's inherent problems, or "quirks" as they like to call them, just don't exist in most other programming languages. If they have used another language, it's usually PHP, which is arguably worse than JavaScript in many ways. While living in this bubble of ignorance, they don't see JavaScript's flaws for what they truly are.
JS and Python offer comparable expressiveness for most programming tasks: basic imperative language features, first class functions, closures etc. If you miss list comprehensions, a better syntax for lambdas or classes, go ahead and use the favorite JS shorthand - coffeescript. It _really_ is JS. Even if you don't use coffee, having first class functions would let you write some of those missing features in a library (albeit with a slightly clunkier syntax).
Sure there are nuances, like scoping rules. On the plus side, having a single programming language on the server and client saves some time. Also, most of the libraries being async in nature helps in typical I/O heavy apps.
I draw these inferences from a medium sized JS project I have going on at http://www.poe3.com (source: https://github.com/jeswin/poetry-source). I am fairly convinced that JS did save me a lot of time. Interested in seeing how you came to your conclusions.
Wow.
Don't get me wrong, C is outstanding in its problem domain, but it certainly has no shortage of rope with which to hang yourself.
"These people also can see how it lacks the language features necessary for large-scale, multi-developer, distributed development, and then the subsequent maintenance of such projects."
The Gmail team might disagree.
And, yes, C is a far more sensible programming language than JavaScript is. C may not be perfectly defined, but at least it isn't full of stupid gotchas like JavaScript is. C doesn't bungle such basic things as equality checks, for instance. C also doesn't include idiocy like semicolon insertion.
C can be risky to use in some cases because it offers an extremely high degree of power and flexibility to the programmer.
JavaScript is risky to use in all cases because it is rife with design mistakes and other inherent flaws that make it much too difficult to write reliable, maintainable code.
"C doesn't bungle such basic things as equality checks, for instance."
2.0 == 2?
False.
Most people would consider that a flaw. As programmers we understand that integers and floats are different in the computer, but that's not how it works in math.
"C also doesn't include idiocy like semicolon insertion."
You must really hate the languages that don't use semicolons at all. :-)
Compilers have gotten a lot better about warning about these situations, but they're far from perfect. In any case, "produces a compiler warning" and "doesn't produce a compiler warning" isn't "==" behavior.
We won't even go into why having a logical comparison return an integer result is questionable. Yes, it's very convenient sometimes, but it's still an example of the type of "flaw" that he doesn't like in Javascript.
Note that this is precisely why Javascript has ===, widely regarded as one of its "flaws".
Hard to disagree with this. That said, I think even JavaScript guru's generally agree that the language itself is actually pretty awful unless you know all of the legacy quirks and WTFs it is dragging along.
When discussing the merits of programming languages, the observation that "JavaScript is the best we have for browser-based development" or "it's possible to write really awesome things with JavaScript" just doesn't cut it for me. Either you acknowledge and accept JavaScript's deficiences and don't try to sugar-coat them, or you refrain from trying to objectively rank it against other languages at all.
My personal opinion is that you simply cannot reasonably maintain that JavaScript is a 'good programming language', for the simple fact that before can say you are proficient with it, you likely have had to deal with multiple WTF's you'll never run into with (most) other languages. Other dynamic VM-based language exist that are much better than JavaScript, but just like the QWERTY keyboard layout, we're stuck with it.
Are you confusing pure JS with DOM APIs and xbrowser quirks? Pure ES5 (or 6) is actually a very lovely language to work in, and now thanks to Node, we can.
Maybe I'm just so used to the quirks that I don't see them as a problem any more.
To jog your memory, here's a list of questionable design decisions I can think of off the top of my head:
Automatic semicolon insertion and a broken == operator
A language shouldn't try to guess the programmer's intention, but rather fail cleanly on ambiguous cases.
Function scope and global by default
Frankly, I'm appalled by how many dynamic languages get it wrong. Lexical block scoping with mandatory declarations are by far the most sane approach I've come accross, and the only P-language (Perl, Python, PHP with Ruby and Javascript as honorary members) that gets it right is (strict-mode) Perl.
Weird object system
While actually protypal, the constructor-with-prototype-property semantics add a pseudo-class based overlay without an obvious mechanism for object extension and code reuse.
These things don't matter in practice, although we could go on arguing about them. If a language has basic hygiene like first class functions I can build apps with it.
I do, but others disagree. My point is that when parsing fails, insert a semicolon and try again doesn't look very appealing from my personal criteria of language design.
- If you needed type checking, use ===
Which was added to the language after it was realized that the original semantics of == might not have been that well thought out.
- Function scope and object system, what's wrong with it?
Block scoping provides a finer level of encapsulation than function scope. Do you think `let` was added to the language (JS1.7, ECMA6) just for the heck of it?
As for the object system: Instead of using one of the well-known approaches (protoypal with cloning or class-based with inheritance), JS comes with a weird hybrid system inferior to both. Of course JS allows both approaches, but does not provide syntactic support for either, which makes them clumsy to use and open to fragmentation.
I see 2 problems with this point of view:
1) Ever programmer sometimes makes mistakes, such as forgetting a semicolon, or writing '==' instead of '===' 2) This assumes that anyone writing JavaScript knows about all these gotcha's
We can sit here all day arguing about 'how bad' some of the things JavaScript does or does not, but that's not the point. Most other languages have none of these issues, and if tomorrow somehow all browsers on earth would magically be able to run some kind of clean alternative to JavaScript, I'm pretty sure everyone would immediately jump on it.
Sure, Crockford is probably the best example. But the same is true from many languages that became popular before 2000. C is notorious for its pointer magic and buffer overflows. C++ is notorious for being an "expert language" that takes years to master. Java is hated for being very verbose. I know someone, long term (Ex-)Rubyist, hating the language for not scaling well and being hard to debug.
Maybe I'm too pragmatic but I think in every language there is something to hate. (Haven't seriously tried C# though ;)
I think at the end of the day the libraries make up at least 50% of the overall language experience. In the recent years JS has got a number of high quality libraries like jQuery or underscore.js that transparently circumvent many behated JS features. Like awkward checks for undefined or consistent and easy DOM manipulation.
IMHO C++ is a good example for a language in which libraries can hardly make up for the deficiencies because the language is so complex. JS on the contrary does not have so many rules.
Often people wane code javascript like language X but javascript isen't language X! You must learn it like every other language! But if often see people doing javascript "when they need it". Nobody writes C just cause they need it... Normally people just sit down and read a book about C.
While the most widely respected books for other programming languages teach one how to use such languages' features effectively, "JavaScript: The Good Parts" basically says not to use large parts of JavaScript.
That alone should show just how poor of a language it is. You don't have to ignore, or actively not use, so much core functionality when using a good programming language.
Not unlike the process of becoming addicted to heroin.