Javascript is probably an excellent example of something written without any consideration of how it would work at scale (which is exactly what we tend to promote). The idea of it suddenly being used for writing single page applications and entire UIs, and now servers and god knows what else, was probably unthinkable at the time.
It wasn't that long ago when all JS did was put snowflakes on a page, or trails of fire behind your cursor, or annoying sequences of alerts and prompts. And it was called DHTML.
Were it possible - in the 90s - to anticipate the recent surge in popularity of JS, maybe we would have had a totally different language.
That said, these 'gotchas' are just part of learning the language. Same with PHP really. With a sufficient level of experience you tend to forget they actually exist.
The sad part is that there is little effort into changing this. Javascript was clearly not designed for what is being used nowadays, but browsers vendors don't believe in introducing a new client language because apparently it's hard to get everyone to agree to a new standard client language. I wonder if the people behind W3C ever considered discussing this. Those gotchas in the article above are not really a tremedous hassle once you learn to live with them, but nonetheless while working on the client side one is still left wanting more from the language.
Because, fundamentally, replacing any part of the web platform is hard. The last big, breaking, change was GIF -> PNG. HTML -> XHTML might happen once IE < 9 becomes irrelevant, but I doubt it.
But, in the case of JS, there's one major practical constraints: Introducing a new language must not regress performance of JS. (Why? There's an absolute ton of JS on the web. Getting 1% of the web using a new language able to be quicker doesn't matter if you regress 99% of the web.)
You may think, "Sure, that's easy. You just add a second VM, entirely disjoint from JS!". Unfortunately, it's not that easy: if you allow the languages to coexist in the same page, you then need to GC across both languages (as some objects are shared between the two runtimes, primarily those relating to the DOM), and cross-VM GC is an active research area, where nothing has been shown without at least a 10% performance hit to both GC impls.
Well, then, how about having a "generic" VM that runs JS within it? You're going to have an uphill battle to get performance equal to current JS VMs, because their bytecode (ignoring V8 for now!) encodes a lot of high-level semantics of JS, which means any new language, to have good performance, would have to share a lot of semantics with JS. This inevitably puts massive limitations on what any new language can be like, and restricts it to being "JS-esque".
So what can we do? There are two basic options: subset JS, though inevitably this doesn't sort out things like `==` v. `===`, but you can get to something where you can statically check you're using a sane subset (e.g., not using `==`, not using any undefined variables, etc.); or, write some language not overly dissimilar to JS and compile down to JS (the "not overly dissimilar" restriction is a practical necessity as you can't really afford to send large language runtimes and standard libraries over the wire). In both cases, JS is ultimately the target thus it's important to keep on fixing what can be fixed with JS (e.g., the lack of a module system, the lack of memory-efficient data structures), but both can improve the situation over unrestricted JS as it is today.
I was wondering about Native Client, and if it did catch on, if people would settle for just using JS as glue code between the DOM and your NaCl extension. It would open up the opportunity to use any language that can be embedded, but might be too much of a faff for not much gain.
> if you allow the languages to coexist in the same page
What if we didn't? Perhaps each site could decide whether to use the JS VM OR the "new" VM; it's not ideal, but this could work. You know, much like what one would (usually) do server side: choose a language, stick to it.
ECMAScript 6 is hardly more than a few bandaids layered upon the existing stack of bandages applied to the gaping wound that is JavaScript.
It does not get to the core of the problems with JavaScript. It does not make the breaking changes necessary to truly fix the situation. It gives a false sense of improvement, at best.
That's why I didn't literally said nothing at all, and it's great that there's something going on with the language, but it would be even better if we were to start new language from scratch, rethought for today.
My only worry is how long it'll take for ES6 to get adopted. It's one thing to write a spec and implement it into the compiler yourself...it's another thing to write a spec and wait for several key browsers to implement it.
The reasons why others aren't adopting Dart are only partly political, and not for the reasons you make out: the political side of it is that most (all?) other browser vendors would much rather only add a new language with an openly developed specification for it; the technical side is there's no way to integrate it into the browser without taking a performance hit both for Dart and JS.
An open specification, sure. But the specification is for all practical purposes controlled by Google: it's not an open standard as a result. (On the plus side, the specification now looks like it may actually be viable to make an independent implementation, which it certainly wasn't before!)
The performance hit is that inherent of having to have multiple GCs given the multiple VMs. This is part of the reason why support for non-JS VMs didn't get into WebKit proper: <https://lists.webkit.org/pipermail/webkit-dev/2011-December/.... Various citations to research around there are listed in that email.
Dartium doesn't attempt to do cross-VM GS, so that supposed overhead isn't there.
I'm not sure any such overhead would always occur, or would only happen if both VMs were in use and there were cross-heap references. It'd doesn't seem likely that cross-heap GC would have such an impact with only one heap.
i've used javascript for single page apps (i.e. real time trading) in early 00's even before the advent of great frameworks such as jQuery..
and it worked really well! at no point did i hear anyone say "i wish javascript wasn't so limited". it's just a vary playable language that's easy to learn and quick to use to hack things (or create entire frameworks out of). it's no coincidence that it's still so popular.
Nobody is suggesting that other programming languages don't have oddities or problems. But very few, aside from perhaps PHP, are riddled with the huge number of senseless, if not outright stupid, issues we see with JavaScript.
It's pretty telling that Crockford's "JavaScript: The Good Parts", which is the most widely-recommended book by the JavaScript community, essentially says to not use huge parts of the language. One doesn't have to intentionally avoid so much core functionality when using most other programming languages.
Have you actually used non-trivial Javascript in any project? You repeat the exact same thing in _every_ JS thread here, and most of it seems to come not from any real experience in JS.
It could be true writing good JS is a little harder than good Java, especially on the server. This is a consequence of the callback oriented nature of JS frameworks and APIs. Once you get used to it, it wouldn't really matter and there are real performance benefits that come out of it.
As for the many warts people bring up, how hard is it to follow a few good practices? If those trivial issues can't be overcome, that person will have problems programming in any language.
I must admit, I do have a great deal of experience with many programming languages, many frameworks and libraries, many operating systems, and many platforms. Some of this experience predates the web.
I have indeed worked on multiple large JavaScript code bases. Some of this work was in the late 1990s (using Netscape Enterprise Server's support for server-side JavaScript, unfortunately), and some of it within the past few years.
Having worked on large JavaScript-based systems, in addition to ones written in languages like C, C++, Java, C#, Fortran, COBOL, PHP, Erlang and several proprietary languages/platforms, the problems with JavaScript become excruciatingly clear. The wider your experience, the more obvious it becomes how terrible JavaScript is.
The problems with JavaScript, especially for any sizable development projects, run far deeper than merely needing to stick to some "good practices". It just doesn't provide the infrastructure needed for anything but small-scale development. Its many flaws render it further inadequate for any serious use.
Now, that won't stop some people from trying to push it far beyond what it's capable of. The results are never good, however, and generally inferior to what could be obtained when using other technologies.
I love JavaScript, but there's no denying that large aspects of the language are somewhat ill-conceived. Crockford himself says this.
Once you know which pitfalls to avoid it's possible to write some really elegant code, but the mere presence of those pitfalls causes a ton of problems when you bring in engineers from other programming languages.
I find it kind of concerning that when someone criticizes JavaScript, everyone's first response is, "he must not have any experience with the language." That's an unfounded personal attack and ignores the crux of the argument.
Look, we love JavaScript, but it doesn't do us any good to pretend it's perfect. It'd be much easier to ramp up new engineers on the language if we admitted its flaws and made efforts to educate "the right way."
"crockford himself" has done great things fo Javascript but he's also not the last word on it. He himself admits that some of his ideas about JavaScript were wrong and resulted from his pre Javacript baggage. E.g. The model he suggests for conventional inheritance in "The Good Parts" does not, iirc, actually work as advertised and in any event isn't needed.
The interesting thing to me about JavaScript is that insofar as it lacks "crucial" language features it turns out to provide the necessary tools to build them yourself. Exactly gow do you want inheritance or modules or whatever to work? E.g. While JavaScript doesn't impose a module structure it's very easy to come up with one, and because you build it yourself you can tweak it to deal with your exact needs rather than adhering mindlessly to "patterns" developed for working around the shortcomings of more tightly defined languages (Java, cough)
Java programmers moving to JavaScript seem to write horrible code because the freedom to actually just do stuff rather than build boxes with tiny weird-shaped holes cut in them to package pieces of functionality is so alien.
I wish Python, with its (fewer) warts were as ubiquitous and useful as JavaScript, but it's not, and Javascript is pretty darn good.
I'm not disagreeing with you in any way, shape or form. JavaScript is an AWESOME language for both productivity and results. But I think we're doing ourselves a disservice if we assume that anyone jumping right into the language is going to immediately understand it.
Like you said, bad code is somewhat inevitable when you drop a classically-trained OOP programming into JavaScript. And that specifically is not a fault of the language. But I think we can all do a better job of pointing newbies in the right direction.
> If those trivial issues can't be overcome, that person will have problems programming in any language.
No. I've written non-trivial JS code and the amount of possible mistakes that a person writing JS can make is a lot more than say, Python or Ruby. You have to be really really careful and simple things that you shouldn't even have to think about become tedious.
Not to turn this into a JS hate thread, but I'd rather write C code that doesn't pretend to be safe, than write JS code that does, and screws up anyway.
Yes, it's all doable, but working around JS's kinks is terrible. Why? A programming language has one job, and that is to be a good programming language.
Whether I can write a useful program in it is uninteresting, because that's a property of almost all languages, good or bad. The question is whether its a pain.
What you don't understand is that good JS is very hard. It's hard because this language was never designed for application development, it was designed to edit the DOM. Not only is it unhelpful when trying to do things like splitting your code into smaller pieces, do encapsulation, refactoring, write performant code, but it actually HINDERS the programmer when trying to do the above.
This is an anti-programmer programming language. The fact that so many people love it is a bit of a mystery to me and I've actually used it for both DOM manipulation a long time ago and for mobile apps more recently. I will say that it's quite good at being a scripting language for an app UI (QML).
Depends on your definition of "core functionality". Some things stop being core because they're recognised as antifeatures and avoided. This includes huge swathes of many languages that don't get off-handedly derided as often as Javascript.
Javascript is off-handedly derided because it's got so many basic things wrong that never got fixed. If they'd have iterated fast with it by now it would be fine, but it's stuck in the glacial committees. And personally I think they needed to abandon prototypical behaviour which is just confusing and too verbose.
The object declaration is painful, it has variable hoisting and doesn't have proper block scope leading to all sorts of weird bugs, it doesn't have simple namespacing, it didn't have a foreach, it didn't have get/setters until recently and even now the syntax is bad because they wanted to maintain backward compatibility.
Oh and everything's a bloody function. A function is a function. A class is a function. An anonymous method is a function. It can get really hard to read and pick out what a bit of code is actually doing on first pass.
And that's just the big, really simple but important, every day stuff that a normal coder needs to do their job in even the slightest complexity scenario.
I sometimes wonder if the 'other' language that netscape was going to use was really as frustrating as javascript is when you start working on more complex code.
What it did have which most languages didn't have is treating functions as first-class objects and closures. They're brilliant.
Unfortunately almost all other modern languages now have these and javascript still doesn't have all the other goodies so that's one of the many reasons it gets so much hate.
So now compared to any other language it looks so dated and archaic.
I really enjoy writing javascript at times, but as the code gets complex I despise it. And I hate coming back to my old javascript code.
I find some of these thoughts to be be a bit off in their basic premise. For example, "A function is a function. A class is a function. An anonymous method is a function."
Well There are no classes in javascript at all. A constructor is a function in most OO languages. The difference here is the underlying OO implementation.
Anonymous methods are by nature functions as well. Could there be a more succinct syntax for them? Perhaps, but of all of the complaints about javascript this is a relatively minor one.
I would never say that there are not things about JS that don't drive me nuts. But the relatively simplicity of thinking of just about everything being treated equally from a language standpoint gives you a flexibility to work that can be really refreshing.
The relative simplicity is what I mean about really enjoying writing javascript.
The everything is a function is because at least in other languages it's clear what a constructor is, what a function is and what an anonymous method is. They all look distinctly different and have different keywords or declaration syntax. Generally speaking something like:
class Thing
Thing() { } //constructor
function Thing() {} //function
(p) => {} //anonymous method
Visually they are very different. In javascript they all look pretty much the same and have exactly the same syntax.
I don't doubt you're right — it makes me think of some of the legacy portions of Object Pascal — but can you give an example or two of what you are referring to?
Nor does one have to when using JavaScript. Crockford's recommendations are a good starting point for new JS developers, but they're not the word of God on the subject.
> list of gotchas that omits discussion of falsiness
This was something I picked up pretty easily (blame perl, I guess? I blame perl for lots of things.) The weird way in which coersion would interplay with {truth,fals}iness, however, took much longer and involved much weeping and gnashing of teeth.
> And the throwaway comment about JavaScript being poorly designed is facile and annoying Every language anyone uses has warts.
Agreed. The post was helpful (and the link to Crockford's book is arguably the single most helpful thing in the list) but the off-hand comment about ES being poorly designed didn't add anything to the discussion.
Really, he should've used a different title, say "JavaScript Rant"
The author complains about the was language is designed, and says "might", "in some cases", "this is wrong" etc. without showing real examples. And he's also dead wrong on a few facts (like JS being a pure functional language).
Looks like "let's bake something in 5 minutes" and post it to HN to get 57 points for nothing.
I'm ashamed that a lot of rants about languages get so many points here on HN. This article, in particular, is written by a JavaScript ignorant, which for the first time approaches the language. Even worse, "JavaScript the good parts" is a good read, but it shouldn't be promoted as the _de facto_ bible of JavaScript as it is: it's old, outdated, lacks a lot of the recent changes and promotes a lot of patterns which became anti-patterns.
An example of my last sentence: have look at how Titanium SDK (v2.1.x) folks designed their "parasitic inheritance" architecture following Crockford's book. A terrible, unusable, instable, un-hackable (wrong) use of JavaScript.
EDIT: I don't know if Steve Kwan is actually a _noob_ or not, but it looks like. Eg:
identifier = function () {};
this is not one of the examples of "ways to create a function". This is actually an assignement using a function expression. These are the 3 REAL ways:
// As expression, in an assignement or as argument.
(function () { /*...*/ });
// As expression, but with a name given to it.
(function $identifier$ () { /*...*/ });
// As a declaration, which gets HOISTED!!
function $identifier$ () { /*...*/ }
I did not put that there because it was the best syntax. :) I put it there because I felt it was most likely to be understood by someone new to the language. I assume you're implying I should have used {}?
Yes, not for the syntax itself, but for a mere "smell" of code quality. The use of "new Object" is found only in two kind of JS code incredibly old or incredibly badly written.
I hear you completely. But understand that my intent here was not to write idiomatic code, it was to write code that an outsider to JavaScript would understand. I worry that the {} syntax, while simple/elegant/preferred, may be somewhat less obvious to a new person who is unfamiliar with JavaScript's object literals. In any event, I've updated the article to include both ways.
Regarding variable hoisting, I am trying to keep this article short, concise, and focused on the big offenders when it comes to gotchas. The only reason I didn't discuss hoisting is because I felt it would introduce too many concepts at once. To me, hoisting is kind of "level 2," whereas understanding why var is required is "level 1."
And on a side note, I appreciate all the feedback you're providing here - I really do. That's why it's on GitHub and not some blog somewhere. But I would suggest that we separate personal attacks from code criticisms. If you don't like my approach with this article or you find something that's flat-out incorrect, by all means tell me. As a human I am prone to make mistakes - maybe moreso than others. :)
But please avoid making value judgments about a person you don't even know, such as calling them an ignorant. It's bad enough when people behave this way on the internet, but if that kind of mentality starts to seep into your "real world" life too, it'll start having serious effects on team relations and employability.
I'm sorry for my personal stakes at you. And honestly I have to say I'm biased against javascript articles, because I'm so used to find a strong lack of experience and knowledge in them. I appreciate your answer, and please pardon my rudeness.
At the same time you could make a "level 1" article a lot more adherent to reality. For example, you could completely jump over that "function creation" section entirely, and simply do a clear explanation of what an expression is in JavaScript, and how to spot them.
Again, thank you for your personal advices, and thank you for your politeness (as opposed to my manners).
All variables are hoisted to the top of a function, where they are defined as 'undefined'. This is confusing, I know - there is actually a difference between an undefined variable (accessing it will cause a ReferenceError) and a variable defined as 'undefined', which is in many cases identical to null, except in object syntax.
An example you can run in your inspector:
function foo(){
console.log(a);
var a = "string";
}
function bar(){
console.log(a);
}
foo(); // logs 'undefined'
bar(); // throws ReferenceError
Why does this happen?
Well, this is because of the variable hoisting. Before running a function, the interpreter scans for any var definitions and 'hoists' them to the top of the function, where they are set to undefined. This leads to the strange situation where defining a variable after it's been accessed (as in foo()) actually prevents an exception.
The same is true of functions defined with the 'function name(){}' syntax. As opposed to the 'var name = function(){}' syntax, the entire function (including the definition of the function!) is hoisted to the top of the containing function. So this will work:
function foo(){
bar();
function bar(){
console.log("works!");
}
}
foo();
This can be confusing but if used properly can be very helpful in refactoring your code. For instance, there are times when I've easily cleaned up code by just putting them into separate function definitions within the parent function:
// old version
function longFunction(){
// 50 lines of code
// awful, messy
}
function refactoredLongFunction(){
doFirstThing();
doSecondThing();
doThirdThing();
function doFirstThing(){
// ...
}
// other function definitions
}
This prevents a pattern I see in a lot of JS libraries that drives me nuts - defining functions at the top of a closure, then calling them at the bottom. I very much dislike scrolling 100 lines to see the actual action performed by a function. Using the above pattern leads to much more readable code, IMO.
> Before running a function, the interpreter scans for any var definitions and 'hoists' them to the top of the function, where they are set to undefined.
A little off topic, and completely trivial and petty, but it kinda bugs me when people talk about it as if the interpreter is moving variables around.
Moving variables around like that seems like a completely nutty thing to do, because it is. You can't give someone an explanation of the trade-offs as to why Javascript does it, because it doesn't. So hoisting is just presented as another thing Javascript does that makes it weird.
Really it's not actually moving anything, it's just an artefact of the same scoping rules used in lots of languages, compounded by allowing variables to be referenced before they're assigned.
Variables aren't moved, they behave as if they were moved.
In the second, the var myFunction gets hoisted to the top but not the function definition, which is why calling it produces an error. In the first, the whole function gets hoisted to the top.
The gotchas are fine, but the explanations are very poor. I'd like justifications or references.
I would prefer Ben Alman, Douglas Crockford, John Resig, Paul Irish, or one of the many talented people writing about javascript if you were actually interested in understanding the gotcha's on this list.
Also, I wish authors would be careful to distinguish js from jQuery. Yes it's standard now, but preferences change with time.
I tried not to get too deep into the explanations because I really, really wanted to keep this to a short list that could be scanned and grokked.
Truth be told, if someone wants an explanation of some of JS's weirdness, there are far better articles out there they can Google to meet that need. :)
The first one will be hoisted to the top of the function (the whole declaration), the second one won't (the variable will, but not the function expression itself).
EDIT: To clarify:
All variable declarations in Javascript do indeed get hoisted to the top of the scope, but with function declarations even the function value itself gets hoisted. So for instance, this returns 'two':
function foo() {
function one() { return 'one'; }
return one();
function one() { return 'two'; }
}
foo();
But this returns 'one':
function foo() {
var one = function one() { return 'one'; }
return one();
var one = function one() { return 'two'; }
}
foo();
Named functions are generally fine to use (they're hoisted, but otherwise behave the same), but named function expressions (where you both give the function name, and use it as an expression) has some nasty memory leak issues on IE [1].
Some people think its better to ditch named functions completely rather than learn exactly when its problematic and when it's not... which I'm not sure I completely agree with, but its probably a good advice to give to a new JavaScript programmer, as it basically behaves the same minus those issues.
CoffeeScript ended up removing named functions [2] [3] (with the exception of being used for "class" declarations, where its known they're safe) for that reason.
The memory leak issues you're referring to are old and have been fixed. They may be an issue if you are writing code that must support legacy IE, and then only in specific cases. However, if that's not you, then there's no reason not to use named function expressions. There's no other way to completely avoid arguments.callee (which is going away) for recursive reference, and it also makes call stacks and debug messages clearer. You won't think either of those are a real issue until they are.
So no, I disagree that that's good advice to give to a new programmer.
The memory leaks issues are effecting IE <= 8, which still has around 10% market share. Losing one of ten potential customers is not acceptable for most businesses. Unless you're writing server-side JavaScript, or have a specific demographic that uses newer technologies, those kind of bugs are not something that you should ignore.
To address your other points - you can get a recursive reference by simply assigning your function to a variable, `var f = function(){ f(); }`. There's no need for named functions for that.
As for call stacks and debug messages - that was true some time ago, but modern debugging tools can figure out the function name pretty good even if it isn't a named function. I work with CoffeeScript code(who doesn't have named functions) and stack traces are fine.
I think its a better practice to avoid named function expressions on client-side code. Non-expression named functions are fine, but considering that named function doesn't actually have any benefit (I don't consider hoisting a benefit - I prefer to have my functions declared before they're used), I can see why some people would decide to just avoid them altogether.
> To address your other points - you can get a recursive reference by simply assigning your function to a variable, `var f = function(){ f(); }`. There's no need for named functions for that.
> (I don't consider hoisting a benefit - I prefer to have my functions declared before they're used)
> As for call stacks and debug messages - that was true some time ago, but modern debugging tools can figure out the function name pretty good even if it isn't a named function.
All of these ignore the fact that functions are not simply declared once in Javascript and then used later, like in C. It's a dynamic language with first-class functions and function literals. You could assign to a variable in this case, but that's needlessly restricting:
As for IE and memory leaks, I already acquiesced to the need to support it in some cases. Still, for many people it is acceptable to drop support for IE8 despite its general market share, and this leak may not be an issue if the function in question is not related to repeating code. Certainly you should not ignore the issue.
> All of these ignore the fact that functions are not simply declared once in Javascript and then used later, like in C. It's a dynamic language with first-class functions and function literals. You could assign to a variable in this case, but that's needlessly restricting:
>
> asyncFunc(function cb(result) { print(result); });
The assignment itself is an expression too, that returns the assigned value - the function in that case. You can just do that:
var cb;
asyncFunc(cb = function(result) { print(result); })
I would agree that having to declare the variable separately is a bit annoying, but I'm mostly writing CoffeeScript which doesn't require you to explicitly declare variables, so it doesn't really bother me.
Other than hoisting and leaking memory, nameless function expressions can be used to anything that can be done with named functions.
Cannot decide which is a worse language, Javascript or PHP.
It is quite amazing how much effort people putting in to designing the "perfect" language, and yet we continue to see highly flawed languages get popular.
I wonder if we'll ever see a replacement for JS in the browser? Maybe just a JS-strict with all the gunk and strangeness removed (and maybe the libraries cleaned up a LOT).
> Cannot decide which is a worse language, Javascript or PHP.
If you discovered that the answer was one or the other, would it make you a better developer in any way? Would it help solve any problems the world has?
Perhaps you should look more into why the "Gresham's Law of Programming Languages" exists. Maybe the have better documentation, a more friendly user community. Maybe they fix more real-world problems and spend less time mentally masturbating over programmer porn.
PHP by a long shot. For the record, I think JS is a decent language with easily encountered flaws that don't really affect me day to day. The few people I've encountered who think it's the best are...wrong. It has problems and here's the list:
It's long but not THAT long. There is a strict set of JS with some of the gunk removed. I don't think they went far enough but such is life. I'm not expecting a replacement for JS in the browser. AFAICT the browser vendors aren't interested in getting a replacement language standardized. I do expect compile-to-js options becoming more popular.
There are a couple other problems that make building web applications hard but are not the fault of the language:
What I generally find is that people who think JS sucks don't actually know JS. They know Java or C# or something and can, without learning anything, put together something that runs and generally does what they want. Their success (no obvious failures) and comfort with the syntax (except for those damn unexplainable JS bugs) causes an overestimation of their capability.
Overestimation is a problem because their experience in programing allows them to write a complex chunk of code that has the wrong abstractions/organization. It's absolutely awful. The worst 20-150k sloc codebases I've run across were ALL written by Java programmers who tell me JS sucks. The problem was that they're doing it wrong. Applying the right patterns has led to a 50%+ line count reduction in all cases. JS is its own language. The architectural patterns that work come from functional languages and not classy languages. Classy patterns can work but you need to go all-in and add type checking a la Google Closure oriented code and that's rare in the wild. Finally, small modules as in the node.js community generally seem to be working.
On the other end, JS suffers (along with PHP) the part timers. This would be fine except that easy but wrong patterns become standard practice. I fought against the jQuery spaghetti pattern for years only to find people migrating to Backbone, which is better but also flawed–events don't provide state isolation and the simple idempotent view.render() falls apart in larger apps and the workarounds are nuanced or complex. Use Ember or Angular. They are NOT more complex than you'll need unless you're only making brochureware sites.
The third problem is that the DOM sucks. The API is bad and has cross browser issues but jQuery basically won that battle. The remaining and more subtle problem is that it's a mutable global variable that you must interact with. There are a variety of mitigation strategies with the most accessible being two way bindings.
The tone of this article does absolutely nothing to help a new learner. While mostly factually correct, constantly complaining, whining, and saying what a stupid design decision this or that was helps in no way.
Every language has quirks. In the case if js, the things your complaining about like var and function declaration are features of the language.
My apologies if I came across this way. The intent was not to whine about var or function declaration, but rather to provide clear direction about a standardized "okay" way of doing these things without causing yourself undue headaches.
So please don't interpret my calling these issues out as whining. Just trying to make new people aware that they are there. :)
If, on the other hand, I am legitimately WHINING and not realizing it, also feel free to tell me where so I can fix it. Thanks!
Fair enough. Definitely not a personal attack or anything. I used to have the very same thoughts until I really learned how powerful many of those confusing things are.
I've gone through and removed some of the bristly "flavour" language. If you want to scan through it again and look for more offenders I'd be greatly appreciative.
There have been a lot of articles re-hashing Crockford's analysis floating around recently. These have been valuable, but they tend to focus on the same topics in the core language (largely concerned with scope, use of closures, behavior of basic data types, and functional programming). In web development, the DOM and events end up being a more common area where I and other devs are tripped up. A few things I wish I knew before a deep dive into an large scale JavaScript project:
1) Newly added elements will not respond unless events are bound to them. One solution (thinking in jQuery here) is to bind events higher up the DOM.
2) Each line in code may not simply execute in sequence. For example, asynchronous ajax calls require subsequent calls to be nested in callbacks.
Regarding #2, I highly recommend reading Trevor Burnham's excellent book Async JavaScript. It goes into a great deal of detail explaining how async operations work, and ways of dealing with them.
Wow, glad to see this is stirring up a lot of discussion. Thanks for all your contributions guys.
There are a ton of comments down below with a ton of criticisms and suggestions. I will attempt to summarize and respond to the key ones here:
#1: The list is missing a lot of very well-known JavaScript gotchas.
That's intended. My goal here is not to provide a complete, comprehensive list of all known quirks with the language - those exist in far better fashion on the web already. Rather, my goal is to create a simple list of issues that I KNOW will trip up newbies out of the gate.
Oddness with truthiness, undefined and arrays is definitely irksome, but from my experience people tend not to run into those problems until they've already written a good chunk of JS. On the other hand, issues like var, confusion over closures, and the this keyword come up very quickly - almost immediately.
#2: The list seems very negative and biased against JavaScript.
My apologies, as that was not the intent at all. JS is great. But it is also extremely flawed and there are some things flat-out wrong with the language. I'm definitely not the only person who says this, either. :)
It's a great language to work in and you can do some wonderful things with it once you grok it, but if we're going to be completely objective, we have to admit that it has some definite problems that make it hard to learn.
#3: This seems full of preferences, not hard-and fast rules.
That's definitely by design as well. I circulate this list out to my team and so it has my fingerprints all over it.
If this is a real sticking point with you guys and you feel it would be better having that stuff removed, please send me some pull requests and I'll be happy to review.
#4: The author comes across as snarky and unhelpful.
That's just a personality flaw and I apologize for it. :) I didn't want this piece to be dry and I injected a bit of voice. If you feel it's actually detracting from the article, please feel free to shoot me some examples and I'll clean it up.
Oh, and one more thing. If you see anything in there that's flat-out WRONG - not just a preference or stylistic choice, but actually WRONG - by all means, shoot me a pull request! That's what it's there for.
I would just like to point out that people tend to blow the semicolon insertion thing out of proportion. For braces it really only comes up when returning object literals and for other things there are just a couple of features that can bite you (starting lines with parenthesis or array literals and so on)
While semicolon insertion itself does cause many problems, the mere fact that it exists as a "feature" of the language is perhaps a bigger problem.
There's no justifiable reason for it to exist. The drawbacks should have been clear from the moment the concept arose, and it should have been scrapped before ever having been implemented. That's the only sensible response to it, after even a minimal amount of analysis.
A missing semicolon should be treated as an error, causing the execution of the script to be immediately halted, and the programmer notified of it. It is as simple as that.
Other way around - because of braces and many other issues brought up when you try to take advantage of Automatic Semicolon Insertion, that is frowned upon.
I actually find little quick explanations like this extremely pragmatic and useful. I don't do a whole lot of JS, but I certainly need to dive in occasionally. Having quick references like this one readily available is preferable to finding my Crockford book and flipping through the pages. If you need to develop a client-side app or do heavy JS coding, maybe read the Crockford book...but if all you need to do is get some shit working real quick links like this one are invaluable.
This list isn't even well thought out at all and is more just a rant about some random stuff. I'm not a big fan of the javascript type system in any case but this isn't a real critique of it.
At some point just like Monads you just get the javascript type system and don't worry about it anymore. It is what is. No amount of gotchas will get you over the hump; you have to actually understand it. At least it isn't syntax like C++ where you find out in a WTF moment that the parser is doing something insane.
You should jsperf your function definition advice. The standard "function foo() { ... }" way is over 10x faster than the "var foo = function foo() { ... }" way or any other variant.
gotta be honest.. not loving the tone of this post.
40% of it just keeps droning on about how noobs will fall for these traps, and saying things like "If you are new to JavaScript, I suggest avoiding the this keyword".. as if these concepts are so mind blowing noobs minds will melt.
it does bring up a few good points but it could have been a lot shorter.. and how is closure a common js gotcha? the list includes 4 javascript constructs veiled into a rant.
I really didn't want to write that. Ignorance is never really a good solution. :)
But from my experience, someone who is coming into JS for the first time is probably not setting up a complicated object hierarchy - they're probably just trying to figure out how to bind some events to a DOM element and get some basic UI functionality. And they probably don't need to use the this keyword as much as they think they have to.
I completely agree that this could be a bad decision on my part, or at least a very controversial one. But I'd rather have truly new JavaScript developers focus on things like encapsulation and closures before they get too far into the this keyword and constructor/prototype.
It wasn't that long ago when all JS did was put snowflakes on a page, or trails of fire behind your cursor, or annoying sequences of alerts and prompts. And it was called DHTML.
Were it possible - in the 90s - to anticipate the recent surge in popularity of JS, maybe we would have had a totally different language.
That said, these 'gotchas' are just part of learning the language. Same with PHP really. With a sufficient level of experience you tend to forget they actually exist.