GNU ELPA - js2-mode

Description: Improved JavaScript editing mode

Latest: js2-mode-20150909.tar, 2015-Sep-10, 570kB

Home page:

Browse ELPA's repository: CGit or Gitweb

Full description

This JavaScript editing mode supports:

 - strict recognition of the Ecma-262 language standard
 - support for most Rhino and SpiderMonkey extensions from 1.5 and up
 - parsing support for ECMAScript for XML (E4X, ECMA-357)
 - accurate syntax highlighting using a recursive-descent parser
 - on-the-fly reporting of syntax errors and strict-mode warnings
 - undeclared-variable warnings using a configurable externs framework
 - "bouncing" line indentation to choose among alternate indentation points
 - smart line-wrapping within comments and strings
 - code folding:
   - show some or all function bodies as {...}
   - show some or all block comments as /*...*/
 - context-sensitive menu bar and popup menus
 - code browsing using the `imenu' package
 - many customization options


To install it as your major mode for JavaScript editing:

  (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))

Alternatively, to install it as a minor mode just for JavaScript linting,
you must add it to the appropriate major-mode hook.  Normally this would be:

  (add-hook 'js-mode-hook 'js2-minor-mode)

You may also want to hook it in for shell scripts running via node.js:

  (add-to-list 'interpreter-mode-alist '("node" . js2-mode))

To customize how it works:
  M-x customize-group RET js2-mode RET


This mode includes a port of Mozilla Rhino's scanner, parser and
symbol table.  Ideally it should stay in sync with Rhino, keeping
`js2-mode' current as the EcmaScript language standard evolves.

Unlike cc-engine based language modes, js2-mode's line-indentation is not
customizable.  It is a surprising amount of work to support customizable
indentation.  The current compromise is that the tab key lets you cycle among
various likely indentation points, similar to the behavior of python-mode.

This mode does not yet work with "multi-mode" modes such as `mmm-mode'
and `mumamo', although it could be made to do so with some effort.
This means that `js2-mode' is currently only useful for editing JavaScript
files, and not for editing JavaScript within <script> tags or templates.

The project page on GitHub is used for development and issue tracking.
The original homepage at Google Code has outdated information and is mostly

Old versions

js2-mode-20150713.tar2015-Jul-13 560kB
js2-mode-20150202.tar2015-Feb-04 540kB
js2-mode-20141118.tar2014-Nov-19 500kB
js2-mode-20141115.tar2014-Nov-16 500kB
js2-mode-20140114.tar2014-Jan-16 460kB
js2-mode-20131106.tar2013-Nov-08 470kB
js2-mode-20130619.tar2013-Aug-15 460kB
js2-mode-20130619.el2013-Jun-19 428kB
js2-mode-20130608.el2013-Jun-09 428kB
js2-mode-20130510.el2013-May-11 427kB
js2-mode-20130307.el2013-Mar-08 425kB
js2-mode-20130228.el2013-Feb-28 425kB
js2-mode-20130219.el2013-Feb-19 430kB
js2-mode-20130217.el2013-Feb-17 429kB
js2-mode-20090814.el2012-Nov-29 421kB
js2-mode-1.1.el2012-Dec-25 429kB


# History of user-visible changes

## 20150909

* `js2-mode` now derives from `js-mode`. That means the former
  function will run `js-mode-hook`, as well as `js2-mode-hook`. The
  key bindings will default to `js-mode-map` where they're not set in
  `js2-mode-map`. And in Emacs 25 or later (including the snapshot
  builds), `js2-mode` uses the indentation code from `js-mode`.  Where
  feasible, the user options (and functions) now have aliases, but if
  you're using Emacs 25 and you see an indentation-related setting
  that stopped working, try looking for a corresponding one in the
  `js` group: `M-x customize-group RET js RET`.

* New command: `js2-jump-to-definition`. It's bound to `M-.` by
  default, via remapping `js-find-symbol`. To get back to the default
  `M-.` binding (e.g. `find-tag`), put this in your init file:

      (eval-after-load 'js (define-key js-mode-map (kbd "M-.") nil))

## 20150713

* More comprehensive strict mode warnings and syntax errors.
* New minor mode: `js2-highlight-unused-variables-mode`.
* `js2-pretty-multiline-declarations` can take the value `dynamic` now.

## 20150202

Support for:

* [ES6 modules](
* [Short-hand object literals](
* [Method definitions](
* ['u' and 'y' RegExp flags](
* [Computed property names](
* [Class statements and expressions](
* [Template strings](, including tagged ones.

The variable `js2-allow-keywords-as-property-names` has been
removed. Instead we check if `js2-language-version` is 180 or highter.

## 20141115

Support for:

* Unicode characters in identifiers (improved).
* [Delegating yield](
* [ES6 numeric literals]( (octal, binary).
* Harmony [array and generator comprehensions](

## 20131106

Support for:

* [Arrow functions](
* [Generators](
* [Spread operator](

## 20130510

### Support for JSLint global declaration

See the docstring for `js2-include-jslint-globals`.

## 20130216

### We don't rebind `RET` anymore

Because well-behaving major modes aren't supposed to do that.

So pressing it won't continue a block comment, or turn a string into a concatenation.
Pressing `M-j`, however, will.

The options `js2-indent-on-enter-key` and `js2-enter-indents-newline` were also removed.

To bring back the previous behavior, put this in your init file:

(eval-after-load 'js2-mode
  '(define-key js2-mode-map (kbd "RET") 'js2-line-break))

## 20120617

### Support for [default]( and [rest]( parameters

## 20120614

### Support for [for..of loops](

## Older changes

### Popular indentation style

[foo, bar, baz].forEach(function (v) {
    if (validate(v))

[a, b, c].some(function (v) {
    return validate(v);

### Pretty multiline variable declaration

In the original mode,

var foo = 10,
bar = 20,
baz = 30;

In this mode when the value of `js2-pretty-multiline-declarations` is non-nil,

var foo = 10,
    bar = 20,
    baz = 30;

### Abbreviated destructuring assignments

let {a, b}       = {a: 10, b: 20}; // Abbreviated   (Not supported in the original mode)
let {a: a, b: b} = {a: 10, b: 20}; // Same as above (Supported in the original mode)

(function ({responseText}) { /* */ })(xhr); // As the argument of function

for (let [k, { name, age }] in Iterator(obj)) // nested
    print(k, name, age);

### Expression closure in property value

let worker = {
    get age() 20,
    get sex() "male",
    fire: function () _fire()

### Fix for odd indentation of "else if" with no braces

In the original mode,

if (foo)
    return foo;
else if (bar)
return bar;      // here

In this mode,

if (foo)
    return foo;
else if (bar)
    return bar;  // fixed

### Imenu support for function nesting

Supports function nesting and anonymous wrappers:

(function() {
  var foo = function() {
    function bar() { // shown as<definition-1>
      function baz() {} //
      var qux = function() {}; //

Examples of output:

* [jQuery 1.5](
* [Underscore.js](
* [Backbone.js](

For library-specific extension methods like `$.extend` and `dojo.declare`, see [js2-imenu-extras](/mooz/js2-mode/blob/master/js2-imenu-extras.el).

### Undeclared/external variables highlighting

Original mode highlights them only on the left side of assignments:

var house;
hose = new House(); // highlights "hose"

Here they are highlighted in all expressions:

function feed(fishes, food) {
    for each (var fish in fshes) { // highlights "fshes"
        food.feed(fsh); // highlights "fsh"
    hood.discard(); // highlights "hood"

Destructuring assignments and array comprehensions (JS 1.7) are supported:

let three, [one, two] = [1, 2];
thee = one + two; // highlights "thee"

function revenue(goods) {
    // highlights "coast"
    return [price - coast for each ({price, cost} in goods)].reduce(add);