6 ms·
Common JavaScript Gotchas
- Tloewald 14y agoReplace article with link to Crockford and John Resig's advanced JavaScript tutorial. http://ejohn.org/apps/learn/ http://ejohn.org/apps/learn/ Any list of gotchas that omits discussion of falsiness, objects vs arrays, array-like things that aren't arrays, the array sort function... And the throwaway comment about JavaScript being poorly designed is facile and annoying Every language anyone uses has warts.
- PommeDeTerre 14y agoNobody 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.
- joshuacc 14y agoNor 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.
- Tloewald 14y agoDepends 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.
- JasonFruit 14y agoI 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?
- Tloewald 14y ago* case sensitive symbols in C and its derivatives -- thank goodness I can declare int Int. * C declarations (experts can get into flamewars discussing good ways of reading C declarations) * C (and worse C++) keyword overloading * C strings * Most of C++ (i.e. most of C++ - C) * Most Java libraries * Objective C's declarations (which at least have gotten markedly better recently) * Perl's variable prefixes and subroutine declarations (even if you don't mind Perl's other quirks) * semantic whitespace in languages with semantic whitespace * PHP -- which I find useful and perfectly capable of supporting large projects -- is hilariously awful.
- mattmanser 14y agoJavascript 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.
- jeswin 14y agoHave 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.
- andrewvc 14y agoYes, 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.
- manish_gill 14y ago> 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.
- PommeDeTerre 14y agoI 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.
- wuest 14y ago> 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.
- lttlrck 14y agoYay another one. This is what SO community wikis are for.
- UnoriginalGuy 14y agoCannot 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).
- borplk 14y agoI hope to see the day where the web is language agnostic. Why the hell do we have to be tied to one single language?
- PasserBy2 14y agoThe worst part is the hype. Pretending it's cool, like there is a choice.
- blowski 14y ago> 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.
- grayrest 14y agoPHP 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: http://bonsaiden.github.com/JavaScript-Garden/ http://bonsaiden.github.com/JavaScript-Garden/ 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.
- phaedryx 14y agoBecause of semicolon insertion, Allman-style braces are frowned upon. https://www.google.com/search?q=javascript+brace+style https://www.google.com/search?q=javascript+brace+style
- jrajav 14y agoOther 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.
- ufo 14y agoI 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) http://inimino.org/~inimino/blog/javascript_semicolons http://inimino.org/~inimino/blog/javascript_semicolons Sure, its best to always explicitly use semicolons but its not as dangerous to forget them as most make it sound.
- PommeDeTerre 14y agoWhile 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.
- killahpriest 14y agofunction myFunction(arg1, arg2) {}; // This is OK, but... var myFunction = function(arg1, arg2) {}; // This is best! The second option is better, and is properly scoped, but it leads to certain syntax problems once you get into closures. What problems? How does assigning the function to a variable help avoid needing to make a closure for this?
- jrajav 14y agoThe 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();
- nadaviv 14y agoNamed 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. [1] http://kangax.github.com/nfe/#jscript-memory-management http://kangax.github.com/nfe/#jscript-memory-management [2] https://github.com/jashkenas/coffee-script/issues/366#issuecomment-242134 https://github.com/jashkenas/coffee-script/issues/366#issuec... [3] https://github.com/jashkenas/coffee-script/wiki/FAQ https://github.com/jashkenas/coffee-script/wiki/FAQ - "Q: Is there any way to name functions, for reflection and recursion?" edit: formatting
- idbentley 14y agoThe 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.
- stevekwan 14y agoI 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. :)
- Kiro 14y agoThe answer to "Why are there so many different ways to declare a function? What are the differences?" doesn't really answer the question. No error: <script> myFunction(); function myFunction() {}; </script> Error: <script> myFunction(); var myFunction = function() {}; </script> A correct answer should explain why this happens in order to understand what the difference really is about.
- jtdaugh 14y agoSee this answer: http://news.ycombinator.com/item?id=5269731 http://news.ycombinator.com/item?id=5269731 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.
- STRML 14y agoI can take a stab at it. 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. If you'd like to know more about function and variable hoisting, this is a good read: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-...
- FuzzyDunlop 14y agoJavascript 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.
- Mahn 14y agoThe 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.
- quarterto 14y agothere is little effort into changing this Yes, nothing at all. https://wiki.mozilla.org/ES6_plans https://wiki.mozilla.org/ES6_plans
- Mahn 14y agoThat'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.
- PommeDeTerre 14y agoECMAScript 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.
- factorialboy 14y ago>> "Closures are a concept that appear in pure functional languages like JavaScript" Err.. since when did JavaScript become pure functional?
- nicholasjarnold 14y agoThanks for this, bookmarked. 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.
- EzGraphs 14y agoThere 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.
- joshuacc 14y agoRegarding #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.
- lucian1900 14y agoJavaScript is most certainly not a pure functional language.
- geuis 14y agoThe 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.
- stevekwan 14y agoMy 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!
- geuis 14y agoFair 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.
- stevekwan 14y agoI'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.
- babuskov 14y agoTL;DR: Poorly written shallow analysis. 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.
- yuchi 14y agoI'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$ () { /*...*/ }
- nej 14y agoHighly recommend reading "JavaScript: The Good Parts" by Douglas Crockford, it's an excellent book.
- SonicSoul 14y agogotta 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.
- stevekwan 14y agoI 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.
- stevekwan 14y agoWow, 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.
- stevekwan 14y agoOh, 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 see a few of you already have, so thanks!
- PasserBy2 14y agoIt would be much easier to list the parts of JS that work as a non-alien would expect.
- cpleppert 14y agoThis 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.
- Eugen_RS 14y agoSome Gotchas should be cached by the ECMAScript 5's "strict mode", see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode https://developer.mozilla.org/en-US/docs/JavaScript/Referenc...
- rartichoke 14y agoYou 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.
- nkg 14y agoVery instructive. I stumbled upon some of these "gotchas" and had to find a solution by myself then. I felt like I have a duty to share this with my french fellas so I translated your article on my blog (with © and ®) monlouis.tumblr.com