Ask HN: Javascript best practices?
How much does it make sense to decompose your javascript routines into separate files? Do you have .js for related classes and methods and one page wide .js to call everything else?
EDIT: The above was just an example, I'm looking for most things related to JS.
51 comments
[ 3.1 ms ] story [ 115 ms ] threadBetter yet, use Google Page Speed.
+2 Grok Douglas Crockford's DOM theory then optimize how your scripts use the DOM, it is very easy to abuse the DOM, don't. Grok the DOM.
http://code.google.com/p/django-compress/
It allows you to have many different javascript files to separate your code logically, and it automatically compresses them into one file for you for deployment. In this way you don't have to compromise speed for clarity.
If you're interested in advanced JS I highly recommend this book. http://jspro.org/
Might Safari Books Online work for you?
http://www.safaribooksonline.com/
I prefer the physical book to reading from a browser, but if the price is right...
I really liked _Javascript: The Good Parts_:
http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockfor...
Particularly because it's purely about style and code organization, and not about the best way to get consistent DOM access between Gecko, WebKit, and IE.
for various reasons i'm not buying the book. i do strongly recommend reading resig's blog posts. some excellent gems there. i've incorporated some great util functions from these posts, for example.
nothing is as good as working with coders who are better than you, tho ;-)
Most of the js I write involves jQuery. As such, I find it's very useful to separate reusable components into jQuery plugins in separate files. If you don't use jQuery or another library which allows plugins, then it's best to create your own namespaced module.
See the "Module pattern" for more info: http://www.yuiblog.com/blog/2007/06/12/module-pattern/
Depending on the complexity of your code, you might want to look into javascript build systems -- there's at least one for every major web framework.
Here's some advantages they offer: - Allow bunding of many js files into one mega js file. (reduces HTTP requests for faster page loading) - Specify javascript dependencies using special syntax. (easier maintenance) - Versioning support (so users don't get an old cached version of your code)
When bundling js files, I try to aim for a maximum of two js files per page. One contains code which is global to the whole site (this is cached on subsequent views), and the second which contains page specific code.
This causes two issues:
1. Memory leaks from deleted or hidden DOM that is still referenced.
2. Performance. innerHTML is still probably the fastest method of adding elements, as dirty as it seems.
EDIT: I'll add that this functionality, which is part of a general language feature known as a "closure", is incredibly powerful when used successfully, but that's out of the scope of my comment.
I would estimate global variables will cause at least 50% of the headaches an intermediate JavaScript developer experiences. It's particularly bad when you're dealing with rows of data, for example.
Get in the habit of declaring every variable in the top line of the function concerned before you use it. If you haven't already mastered closures, this will make things a lot easier for you.
The one exception I can think of is if you have a lot of JS code, but some of it needs to load faster. In that case you may want to split the code into several files based on load priority. If you go that route you may want to also use multiple asset subdomains or ideally a CDN to minimize latency.
I intentionally make my controller file procedural and then I have a custom life-cycle event controller that fires off events for page init, reload, load data, page unload, etc.. so my developers can just fill in the blanks. Any data access is done by calling methods on a service facade which again is purposefully procedural. The service facade then calls any server side services we need (we don't do form posts any more, JSON is far more robust for submitting data). Finally, we use Dijit for any of our widget and any of our model / utility / OO needs.
I know it's no purely JavaScript best practices, and it is more related to project file layout and architecture, but I find it gives me the best architecture for my team size (100+). It helps me on-board people quickly and graduate their skill set while maintaining clean code and allowing advanced features.
I can start a junior on pure html layout, then we can train them to do controller modification, then to work on service facades and then when they have a good foundation in prototype base OO we can graduate them into building reusable widgets and subsystems for the controller and service facade developers. It works well and allows developers to work proficiently at their skill set without mucking up the whole system.
As well the service facades make it easy to contract out entire web projects while my internal team builds server side services to support the effort. This allows us to expand our work force, to a larger pool, without having to vet new developers to deep into business rules to get them up and running.
I haven't had time to look into this but there's also a project called Doloto to help optimise your javascript, http://research.microsoft.com/en-us/projects/doloto/
* Auto-build docs and script for development and production environemnts (easy to concatenate and then pipe this to YUI Compressor)
* Use an MVC project organization or something like-minded. You can't just throw files representing widgets around.
* Write unit tests. JSUnit and SrewUnit (I prefer the latter) work well for this.
* Format your code nicely (this goes for any code but I find a ton of terribly formatted JS)
* Use one common library for any core object prototype changes (on Element, Array, Function, etc.) and don't modify them further.
* JSLint code you're unsure about.
* The best way to dynamically load code is just to write script tags to the document.
A few style-concerned ones...
* Don't use the module pattern. It's rarely appropriate, hiding methods does nobody good, just use a closure.
* Only create elements when absolutely necessary and destroy ones that you will no longer use. There's no garbage collector in that regard.
* Use a routing system to manipulate and read document.location.hash (and the browser history) so that pages have real URLs and navigate like webpages.
* Callbacks and delegates are great, they should be used all over the place.
* Use events and listeners to connect the parts of your app.
* +1 on not using the module pattern.
Just curious. For large scale projects, do you suggest building on top of existing javascript libraries (i.e. prototype, jQuery, mootools, etc)?
In my opinion, jQuery is suitable for progressive enhancement but not for dedicated apps.
rules on serverside are a bit different. especially the module pattern is a must there.
in the future you might be able to pick one of those module loaders http://wiki.commonjs.org/wiki/CommonJS
http://dev.opera.com/articles/view/javascript-best-practices...
Thanks!
edit: am I stupid? But when you obfuscate, you also radically shorten the length of a JS file, thus making it quicker to download: EG:
function c(g){var m=0;while(m<g.length){var r=g[m];r.l=d(r.n,r.o);if(r.j==true){ r.k=e(r.n,r.o,r.l);}else{r.k=0;}r.t=f(r.l+r.k);m++;}}
However this post was about JS design principles.
For me, this means my Javascript looks more like Python -- it can be a little weird, but switching between the frontend and the backend is easier that way.
I'd also recommend using objects as namespaces if you're not dealing with prototypical objects. It makes grepping easier - you can search for 'Graphs.init' instead of 'init' in this example:
var Graphs = {
};For some reason, people don't follow good advices which require changing code logic, refactoring and such: they follow advices where you need to format everything in the longest possible way and write a lot of boilerplate.
Because it's just easier for some people.
http://javascript.crockford.com/
Conventions:
http://javascript.crockford.com/code.html
and his book "JavaScript The Good Parts" is well worth a read, even to experiences JS developers
http://www.amazon.com/exec/obidos/ASIN/0596517742/wrrrldwide...
http://yuiblog.com/blog/2008/09/26/oojs/
http://yuiblog.com/assets/pdf/oojs-ch-8.pdf
http://mashraqi.com/2008/07/high-performance-ajax-applicatio...
http://www.smashingmagazine.com/2008/09/16/jquery-examples-a...
http://dev.opera.com/articles/view/the-seven-rules-of-unobtr...
http://www.reddit.com/r/programming/comments/7rtxa/has_anyon...
http://code.google.com/p/jslibs/wiki/JavascriptTips