If you find yourself doing substantial hacking on complicated
websites, you’ll probably find yourself needing a decent
major mode for editing JavaScript. There are at least
six different JavaScript major modes out
there — which one should you use?
Let’s take a look at them!

A survey of the various JavaScript major modes

generic-x.el (which comes with Emacs)
contains javascript-generic-mode, which
doesn’t handle indentation well, and fails to correctly
highlight C-style (/* … */) comments. But
it’s fine for short-term use: since it ships with Emacs,
it’s already there when you need it.

To enable it, add (require 'generic-x) to ~/.emacs. This will automatically
associate files with .js extensions with
javascript-generic-mode.

Peter Kruse’s
javascript-mode.el is antiquated. It
hasn’t been updated in many years, and relies on
hilit19, an obsolete syntax highlighting library.
Definitely not recommended.

My recommendation:Karl Landström’s
javascript.el
appears to be the nicest JavaScript mode out there. It handles
indentation well, and both C- and C++-style (//
…) comments. A winner! To use, place javascript.el in a directory inside
load-path and add the following to your ~/.emacs:

There’s also ecmascript-mode.el,
which is a derived mode from java-mode. It
doesn’t appear to do anything that javascript.el doesn’t do, and it
unconditionally makes font-lock-builtin-face bold,
regardless of your personal settings. Thanks to krupan and
Mathias for the link.

MozRepl comes with its own js-mode.el, which appears to be a very
minimal variant on cc-mode. Thanks to RetroJ for
pointing this out.

Robustness tip: simple failover

Say you’ve installed javascript.el on machine A but not on
machine B. Ideally, your ~/.emacs
file should detect if javascript.el is installed: if it is, it
should use it, but if it isn’t, it should fall back on
javascript-generic-mode from generic-x.el. This is pretty easy stuff.
First, requiregeneric-x as above.
Then check for the presence of javascript.el, and configure it if
it’s present:

This work is licensed to you under version 2 of the GNUGeneral
Public License.
Alternatively, you may choose to receive this work under any
other license that grants the right to use, copy, modify, and/or
distribute the work, as long as that license imposes the
restriction that derivative works have to grant the same rights
and impose the same restriction.
For example, you may choose to receive this work under the GNUFree Documentation
License, the CreativeCommonsShareAlike
License, the XEmacs manual license, or similar licenses.

Comments

Here's how I do thus and such only if a particular library is
available:

Two things: Using locate-library with autoloads
instead of require means that the library is only
loaded when I actually go to use it. But, in the cases where you
want to use require, it takes an optional
NOERROR argument, so you don’t need your
condition-case wrapper.

I might have had to tweak something to get it to work, I don't
remember, but I think it basically works in GNU Emacs. It's not
as nice as javascript.el, but it has the advantage
that there's a javascript-shell mode.

There is also a js-mode that is packaged with
MozRepl. That said, I have yet to find a satisfactory mode for
editing javascript, and I'm starting to believe that the world
needs a truly good ecmascript-mode, built from the
ground up, according to the spec. (unfortunately that name is
taken) Once a good ecmascript-mode was completed,
javascript-mode and actionscript-mode
could be trivially derived from it. The universal lack of
support for many perfectly valid javascript constructs, like
anonymous objects, nested functions, functions as parameters to
functions, &#38;c., makes me wonder if deriving from
cc-mode is a poor choice and the fatal flaw in all
of the existing modes.

I tried out Karl Landström’s javascript.el and it is very nice, but one bug that annoyed me to no end was the lack of word-boundary acknowledgment in the keyword regular expressions. This meant that words like "input" and "undo" were -partially- hilited, and it also affected the indenting of my "initialize" methods (a result of js-indent-operator-re not looking at word boundaries.) I fixed this by affixing word-boundary sequences to both ends of the strings returned by the calls to regexp-opt.