1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

[CS2] Docs updates (#4536)

* Docs: named functions and function declarations

* No more prototypal `extends`; update docs and example

* More comprehensive documentation of the existential operator; closes #1631

* Better document operators, including `from`

* No fat arrow class methods anymore

* Destructuring shouldn’t say that default values are applied in case of undefined or null

* Spinoff generator and async functions into their own sections; reorder things so that the sections on functions come just before classes, and destructuring goes next to the operators (which discuss assignment)

* Rewrite “CoffeeScript 2” section, making it less practical and more explanatory; move practical info into “Usage”

* Update “Variable Scoping and Lexical Safety” section to remove incorrect reference to Ruby (fixes #2360), add missing details about the safety wrapper, add note about `let`/`const`.

* Updated browser compiler

* Updated docs

* Rewrite Literate CoffeeScript breaking changes

* Split apart the “Breaking Changes” and “Unsupported Features” sections into separate sidebar items and files

* Add example of `not in`, closes #3281

* Fix words in bold that should be in backticks

* Consolidate some breaking changes sections

* Add Node API documentation; closes #3551

* Move the chaining documentation out of the changelog into its own section
This commit is contained in:
Geoffrey Booth 2017-05-05 19:44:11 -07:00 committed by GitHub
parent eba271db5b
commit b28e398396
37 changed files with 939 additions and 698 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -860,9 +860,8 @@ test "Assignment to variables similar to helper functions", ->
extend = 3
hasProp = 4
value: 5
method: (bind, bind1) => [bind, bind1, extend, hasProp, @value]
{method} = new B
arrayEq [1, 2, 3, 4, 5], method 1, 2
method: (bind, bind1) -> [bind, bind1, extend, hasProp, @value]
arrayEq [1, 2, 3, 4, 5], new B().method 1, 2
modulo = -1 %% 3
eq 2, modulo
@ -1247,42 +1246,20 @@ test "classes with JS-keyword properties", ->
ok instance.name() is 'class'
test "Classes with methods that are pre-bound to the instance, or statically, to the class", ->
test "Classes with methods that are pre-bound statically, to the class", ->
class Dog
constructor: (name) ->
@name = name
bark: =>
"#{@name} woofs!"
@static = =>
new this('Dog')
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
ok fido.bark() is 'Spark woofs!'
obj = func: Dog.static
ok obj.func().name is 'Dog'
test "a bound function in a bound function", ->
class Mini
num: 10
generate: =>
for i in [1..3]
=>
@num
m = new Mini
eq (func() for func in m.generate()).join(' '), '10 10 10'
test "contructor called with varargs", ->
class Connection
@ -1587,21 +1564,6 @@ test "#1182: execution order needs to be considered as well", ->
@B: makeFn 2
constructor: makeFn 3
test "#1182: external constructors with bound functions", ->
fn = ->
{one: 1}
this
class B
class A
constructor: fn
method: => this instanceof A
ok (new A).method.call(new B)
test "#1372: bound class methods with reserved names", ->
class C
delete: =>
ok C::delete
test "#1380: `super` with reserved names", ->
class C
do: -> super()
@ -1670,7 +1632,7 @@ test "#1842: Regression with bound functions within bound class methods", ->
@unbound: ->
eq this, Store
instance: =>
instance: ->
ok this instanceof Store
Store.bound()
@ -1833,57 +1795,6 @@ test "extending native objects works with and without defining a constructor", -
ok overrideArray instanceof OverrideArray
eq 'yes!', overrideArray.method()
test "#2782: non-alphanumeric-named bound functions", ->
class A
'b:c': =>
'd'
eq (new A)['b:c'](), 'd'
test "#2781: overriding bound functions", ->
class A
a: ->
@b()
b: =>
1
class B extends A
b: =>
2
b = (new A).b
eq b(), 1
b = (new B).b
eq b(), 2
test "#2791: bound function with destructured argument", ->
class Foo
method: ({a}) => 'Bar'
eq (new Foo).method({a: 'Bar'}), 'Bar'
test "#2796: ditto, ditto, ditto", ->
answer = null
outsideMethod = (func) ->
func.call message: 'wrong!'
class Base
constructor: ->
@message = 'right!'
outsideMethod @echo
echo: =>
answer = @message
new Base
eq answer, 'right!'
test "#3063: Class bodies cannot contain pure statements", ->
throws -> CoffeeScript.compile """
class extends S
@ -2095,9 +2006,6 @@ test "`this` access after `super` in extended classes", ->
eq result.super, this
eq result.param, @param
eq result.method, @method
ok result.method isnt Test::method
method: =>
nonce = {}
new Test nonce, {}
@ -2117,8 +2025,6 @@ test "`@`-params and bound methods with multiple `super` paths (blocks)", ->
super 'not param'
eq @name, 'not param'
eq @param, nonce
ok @method isnt Test::method
method: =>
new Test true, nonce
new Test false, nonce
@ -2137,16 +2043,13 @@ test "`@`-params and bound methods with multiple `super` paths (expressions)", -
eq (super 'param'), @;
eq @name, 'param';
eq @param, nonce;
ok @method isnt Test::method
)
else
result = (
eq (super 'not param'), @;
eq @name, 'not param';
eq @param, nonce;
ok @method isnt Test::method
)
method: =>
new Test true, nonce
new Test false, nonce
@ -2348,7 +2251,7 @@ test "super in a bound function", ->
make: -> "Making a #{@drink}"
class B extends A
make: (@flavor) =>
make: (@flavor) ->
super() + " with #{@flavor}"
b = new B('Machiato')
@ -2356,7 +2259,7 @@ test "super in a bound function", ->
# super in a bound function in a bound function
class C extends A
make: (@flavor) =>
make: (@flavor) ->
func = () =>
super() + " with #{@flavor}"
func()
@ -9638,6 +9541,28 @@ test "export default object", ->
};"""
eq toJS(input), output
test "export default implicit object", ->
input = "export default foo: 'bar', baz: 'qux'"
output = """
export default {
foo: 'bar',
baz: 'qux'
};"""
eq toJS(input), output
test "export default multiline implicit object", ->
input = """
export default
foo: 'bar',
baz: 'qux'
"""
output = """
export default {
foo: 'bar',
baz: 'qux'
};"""
eq toJS(input), output
test "export default assignment expression", ->
input = "export default foo = 'bar'"
output = """
@ -10855,6 +10780,18 @@ test "#4324: Shorthand after interpolated key", ->
eq 1, obj[1]
eq 2, obj.a
test "#1263: Braceless object return", ->
fn = ->
return
a: 1
b: 2
c: -> 3
obj = fn()
eq 1, obj.a
eq 2, obj.b
eq 3, obj.c()
</script>
<script type="text/x-coffeescript" class="test" id="operators">
# Operators
@ -12115,16 +12052,6 @@ test "#1183: super + closures", ->
ret
eq (new B).foo(), 10
test "#2331: bound super regression", ->
class A
@value = 'A'
method: -> @constructor.value
class B extends A
method: => super()
eq (new B).method(), 'A'
test "#3259: leak with @-params within destructured parameters", ->
fn = ({@foo}, [@bar], [{@baz}]) ->
foo = bar = baz = false

View file

@ -1,4 +1,18 @@
# Helper functions
hasProp = {}.hasOwnProperty
extend = (child, parent) ->
ctor = ->
@constructor = child
return
for key of parent
if hasProp.call(parent, key)
child[key] = parent[key]
ctor.prototype = parent.prototype
child.prototype = new ctor
child
A = ->
B = ->
B extends A
extend B, A
B.prototype.foo = -> A::foo.apply this, arguments

View file

@ -1,4 +1,5 @@
for filename in list
do (filename) ->
if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db']
fs.readFile filename, (err, contents) ->
compile filename, contents.toString()

View file

@ -0,0 +1,4 @@
major = 'Computer Science'
unless major?
signUpForClass 'Introduction to Wines'

View file

@ -0,0 +1,2 @@
if window?
environment = 'browser (probably)'

View file

@ -0,0 +1,9 @@
## Async Functions
ES2017s [async functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) are supported through the `await` keyword. Like with generators, there's no need for an `async` keyword; an async function in CoffeeScript is simply a function that awaits.
Similar to how `yield return` forces a generator, `await return` may be used to force a function to be async.
```
codeFor('async', true)
```

View file

@ -1,142 +1,3 @@
## Breaking Changes From CoffeeScript 1.x to 2
CoffeeScript 2 aims to output as much idiomatic ES2015+ syntax as possible with as few breaking changes from CoffeeScript 1.x as possible. Some breaking changes, unfortunately, were unavoidable.
<section id="breaking-changes-default-values">
### Default values for function parameters and destructured elements
Per the [ES2015 spec regarding function default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) and [destructuring default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Default_values), default values are only applied when a value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the value was `null`.
```
codeFor('breaking_change_function_parameter_default_values', 'f(null)')
```
```
codeFor('breaking_change_destructuring_default_values', 'a')
```
</section>
<section id="breaking-changes-bound-generator-functions">
### Bound generator functions
Bound generator functions, a.k.a. generator arrow functions, [arent allowed in ECMAScript](http://stackoverflow.com/questions/27661306/can-i-use-es6s-arrow-function-syntax-with-generators-arrow-notation). You can write `function*` or `=>`, but not both. Therefore, CoffeeScript code like this:
```coffee
f = => yield this
# Throws a compiler error
```
Needs to be rewritten the old-fashioned way:
```
codeFor('breaking_change_bound_generator_function')
```
</section>
<section id="breaking-changes-classes">
### Classes are compiled to ES2015 classes
ES2015 classes and their methods have some restrictions beyond those on regular functions.
Class constructors cant be invoked without `new`:
```coffee
(class)()
# Throws a TypeError at runtime
```
Derived (extended) class `constructor`s cannot use `this` before calling `super`:
```coffee
class B extends A
constructor: -> this
# Throws a compiler error
```
Class methods cant be used with `new` (uncommon):
```coffee
class Namespace
@Klass = ->
new Namespace.Klass
# Throws a TypeError at runtime
```
</section>
<section id="breaking-changes-bare-super">
### Bare `super`
Due to a syntax clash with `super` with accessors, bare `super` no longer compiles to a super call forwarding all arguments.
```coffee
class B extends A
foo: -> super
# Throws a compiler error
```
Arguments can be forwarded explicitly using splats:
```
codeFor('breaking_change_super_with_arguments')
```
Or if you know that the parent function doesnt require arguments, just call `super()`:
```
codeFor('breaking_change_super_without_arguments')
```
</section>
<section id="breaking-changes-super-in-non-class-methods">
### `super` in non-class methods
In CoffeeScript 1.x it is possible to use `super` in more than just class methods, such as in manually prototype-assigned functions:
```coffee
A = ->
B = ->
B extends A
B.prototype.foo = -> super arguments...
# Throws a compiler error
```
Due to the switch to ES2015 `super`, this is no longer supported. The above case could be refactored to:
```
codeFor('breaking_change_super_in_non-class_methods_refactor_with_apply')
```
or
```
codeFor('breaking_change_super_in_non-class_methods_refactor_with_class')
```
</section>
<section id="breaking-changes-dynamic-class-keys-exclude-executable-class-scope">
### Dynamic class keys exclude executable class scope
Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods cant use values from the executable class body unless the methods are assigned in prototype style.
```coffee
class A
name = 'method'
"#{name}": -> # This method will be named 'undefined'
@::[name] = -> # This will work; assigns to `A.prototype.method`
```
</section>
<section id="breaking-changes-literate-coffeescript">
### Literate CoffeeScript now parsed by a Markdown library
The CoffeeScript 1.x implementation of Literate CoffeeScript relies on indentation to tell apart code blocks from documentation, and as such it can get confused by Markdown features that also use indentation like lists. In CoffeeScript 2 this has been refactored to now use [Markdown-It](https://github.com/markdown-it/markdown-it) to detect Markdown sections rather than just looking at indentation. The only significant difference is that now if you want to include a code block in documentation, as opposed to the compiler recognizing that code block as code, it must have at least one line fully unindented. Wrapping it in HTML tags is no longer sufficient.
Code blocks interspersed with lists may need to be refactored. In general, code blocks should be separated by a blank line between documentation, and should maintain a consistent indentation level—so an indentation of one tab (or whatever you consider to be a tab stop, like 2 spaces or 4 spaces) should be treated as your codes “left margin,” with all code in the file relative to that column.

View file

@ -0,0 +1,14 @@
### Bound generator functions
Bound generator functions, a.k.a. generator arrow functions, [arent allowed in ECMAScript](http://stackoverflow.com/questions/27661306/can-i-use-es6s-arrow-function-syntax-with-generators-arrow-notation). You can write `function*` or `=>`, but not both. Therefore, CoffeeScript code like this:
```coffee
f = => yield this
# Throws a compiler error
```
Needs to be rewritten the old-fashioned way:
```
codeFor('breaking_change_bound_generator_function')
```

View file

@ -0,0 +1,36 @@
### Classes are compiled to ES2015 classes
ES2015 classes and their methods have some restrictions beyond those on regular functions.
Class constructors cant be invoked without `new`:
```coffee
(class)()
# Throws a TypeError at runtime
```
Derived (extended) class `constructor`s cannot use `this` before calling `super`:
```coffee
class B extends A
constructor: -> this
# Throws a compiler error
```
Class methods cant be used with `new` (uncommon):
```coffee
class Namespace
@Klass = ->
new Namespace.Klass
# Throws a TypeError at runtime
```
Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods cant use values from the executable class body unless the methods are assigned in prototype style.
```coffee
class A
name = 'method'
"#{name}": -> # This method will be named 'undefined'
@::[name] = -> # This will work; assigns to `A.prototype.method`
```

View file

@ -0,0 +1,11 @@
### Default values for function parameters and destructured elements
Per the [ES2015 spec regarding function default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) and [destructuring default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Default_values), default values are only applied when a value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the value was `null`.
```
codeFor('breaking_change_function_parameter_default_values', 'f(null)')
```
```
codeFor('breaking_change_destructuring_default_values', 'a')
```

View file

@ -0,0 +1,7 @@
### Literate CoffeeScript parsing
CoffeeScript 2s parsing of Literate CoffeeScript has been refactored to now be more careful about not treating indented lists as code blocks; but this means that all code blocks (unless they are to be interpreted as comments) must be separated by at least one blank line from lists.
Code blocks should also now maintain a consistent indentation level—so an indentation of one tab (or whatever you consider to be a tab stop, like 2 spaces or 4 spaces) should be treated as your codes “left margin,” with all code in the file relative to that column.
Code blocks that you want to be part of the commentary, and not executed, must have at least one line (ideally the first line of the block) completely unindented.

View file

@ -0,0 +1,43 @@
### `super` and `extends`
Due to a syntax clash with `super` with accessors, “bare” `super` (the keyword `super` without parentheses) no longer compiles to a super call forwarding all arguments.
```coffee
class B extends A
foo: -> super
# Throws a compiler error
```
Arguments can be forwarded explicitly using splats:
```
codeFor('breaking_change_super_with_arguments')
```
Or if you know that the parent function doesnt require arguments, just call `super()`:
```
codeFor('breaking_change_super_without_arguments')
```
CoffeeScript 1.x allowed the `extends` keyword to set up prototypal inheritance between functions, and `super` could be used manually prototype-assigned functions:
```coffee
A = ->
B = ->
B extends A
B.prototype.foo = -> super arguments...
# Last two lines each throw compiler errors in CoffeeScript 2
```
Due to the switch to ES2015 `extends` and `super`, using these keywords for prototypal functions are no longer supported. The above case could be refactored to:
```
codeFor('breaking_change_super_in_non-class_methods_refactor_with_apply')
```
or
```
codeFor('breaking_change_super_in_non-class_methods_refactor_with_class')
```

View file

@ -0,0 +1,7 @@
## Chaining Function Calls
Leading `.` closes all open calls, allowing for simpler chaining syntax.
```
codeFor('chaining')
```

View file

@ -206,11 +206,6 @@ releaseHeader('2014-01-28', '1.7.0', '1.6.3')
* When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with `require 'coffeescript/register'` or `CoffeeScript.register()`. Also for configuration such as Mochas, use **coffeescript/register**.
* Improved error messages, source maps and stack traces. Source maps now use the updated `//#` syntax.
* Leading `.` now closes all open calls, allowing for simpler chaining syntax.
```
codeFor('chaining')
```
* Added `**`, `//` and `%%` operators and `...` expansion in parameter lists and destructuring expressions.
* Multiline strings are now joined by a single space and ignore all indentation. A backslash at the end of a line can denote the amount of whitespace between lines, in both strings and heredocs. Backslashes correctly escape whitespace in block regexes.
* Closing brackets can now be indented and therefore no longer cause unexpected error.

View file

@ -1,21 +1,17 @@
## CoffeeScript 2
### Why CoffeeScript When Theres ES2015+?
### Whats New In CoffeeScript 2?
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript `=>` becomes an ES `=>`, a CoffeeScript `class` becomes an ES `class` and so on. With the exception of modules (`import` and `export` statements), all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. You can [run the tests in your browser](http://coffeescript.org/v<%= majorVersion %>/test.html) to see if your browser can do the same; Chrome has supported all features since version 55.
Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES `class` keyword, its possible to `extend` an ES class; that wasnt possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like [function parameter default values](#breaking-changes-default-values) should behave the same in CoffeeScript as in JavaScript.
Many ES2015+ features have been backported to CoffeeScript 1.11 and 1.12, including [modules](#modules), [`for…of`](#generator-iteration), and [tagged template literals](#tagged-template-literals). One major new feature unique to CoffeeScript 2 is support for ES2017s [async functions](#async-functions). More details are in the [changelog](#changelog).
There are very few [breaking changes from CoffeeScript 1.x to 2](#breaking-changes); we hope the upgrade process is smooth for most projects.
### Why CoffeeScript When Theres ES2015?
CoffeeScript introduced many new features to the JavaScript world, such as [`=>`](#fat-arrow) and [destructuring](#destructuring) and [classes](#classes). We are happy that ECMA has seen their utility and adopted them into ECMAScript.
CoffeeScripts intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been _simplicity:_ not just removing JavaScripts “bad parts,” but providing a cleaner, terser syntax that uses less punctuation and enforces indentation, to make code easier to read and reason about. Increased clarity leads to increased quality, and fewer bugs. This benefit of CoffeeScript remains, even in an ES2015+ world.
### ES2015+ Output
CoffeeScript 2 supports many of the latest ES2015+ features, output using ES2015+ syntax. If youre looking for a single tool that takes CoffeeScript input and generates JavaScript output that runs in any JavaScript runtime, assuming you opt out of certain newer features, stick to the [CoffeeScript 1.x branch](/v1/). CoffeeScript 2 [breaks compatibility](#breaking-changes) with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript `=>` becomes an ES `=>`; a CoffeeScript `class` becomes an ES `class`; and so on).
Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibility to either ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like [Babel](http://babeljs.io/), [Rollup](https://github.com/rollup/rollup) or [Traceur Compiler](https://github.com/google/traceur-compiler). In general, [CoffeeScript 2s output is supported as is by Node.js 7.6+](http://node.green/), except for modules which require transpilation.
There are many great task runners for setting up JavaScript build chains, such as [Gulp](http://gulpjs.com/), [Webpack](https://webpack.github.io/), [Grunt](https://gruntjs.com/) and [Broccoli](http://broccolijs.com/). If youre looking for a very minimal solution to get started, you can use [babel-preset-env](https://babeljs.io/docs/plugins/preset-env/) and the command line:
```bash
npm install --global coffeescript@next
npm install --save-dev coffeescript@next babel-cli babel-preset-env
coffee -p *.coffee | babel --presets env > app.js
```
CoffeeScripts intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been _simplicity:_ not just removing JavaScripts “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015 world.

View file

@ -1,8 +1,8 @@
## If, Else, Unless, and Conditional Assignment
**If/else** statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. Theres also a handy postfix form, with the `if` or `unless` at the end.
`if`/`else` statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. Theres also a handy postfix form, with the `if` or `unless` at the end.
CoffeeScript can compile **if** statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular **if** statement on a single line.
CoffeeScript can compile `if` statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular `if` statement on a single line.
```
codeFor('conditionals')

View file

@ -36,4 +36,4 @@ Destructuring assignment is also useful when combined with class constructors to
codeFor('constructor_destructuring', 'tim.age + " " + tim.height')
```
The above example also demonstrates that if properties are missing in the destructured object or array, you can, just like in JavaScript, provide defaults. The difference with JavaScript is that CoffeeScript, as always, treats both null and undefined the same.
The above example also demonstrates that if properties are missing in the destructured object or array, you can, just like in JavaScript, provide defaults. Note though that unlike with the existential operator, the default is only applied with the value is missing or `undefined`—[passing `null` will set a value of `null`](#breaking-changes-default-values), not the default.

View file

@ -1,17 +1,37 @@
## The Existential Operator
Its a little difficult to check for the existence of a variable in JavaScript. `if (variable) …` comes close, but fails for zero, the empty string, and false. CoffeeScripts existential operator `?` returns true unless a variable is **null** or **undefined**, which makes it analogous to Rubys `nil?`
Its a little difficult to check for the existence of a variable in JavaScript. `if (variable) …` comes close, but fails for zero, the empty string, and false (to name just the most common cases). CoffeeScripts existential operator `?` returns true unless a variable is `null` or `undefined` or undeclared, which makes it analogous to Rubys `nil?`.
It can also be used for safer conditional assignment than `||=` provides, for cases where you may be handling numbers or strings.
It can also be used for safer conditional assignment than the JavaScript pattern `a = a || value` provides, for cases where you may be handling numbers or strings.
```
codeFor('existence', 'footprints')
```
The accessor variant of the existential operator `?.` can be used to soak up null references in a chain of properties. Use it instead of the dot accessor `.` in cases where the base value may be **null** or **undefined**. If all of the properties exist then youll get the expected result, if the chain is broken, **undefined** is returned instead of the **TypeError** that would be raised otherwise.
Note that if the compiler knows that `a` is in scope and therefore declared, `a?` compiles to `a != null`, _not_ `a !== null`. The `!=` makes a loose comparison to `null`, which does double duty also comparing against `undefined`. The reverse also holds for `not a?` or `unless a?`.
```
codeFor('existence_declared')
```
If a variable might be undeclared, the compiler does a thorough check. This is what JavaScript coders _should_ be typing when they want to check if a mystery variable exists.
```
codeFor('existence_undeclared')
```
The accessor variant of the existential operator `?.` can be used to soak up null references in a chain of properties. Use it instead of the dot accessor `.` in cases where the base value may be `null` or `undefined`. If all of the properties exist then youll get the expected result, if the chain is broken, `undefined` is returned instead of the `TypeError` that would be raised otherwise.
```
codeFor('soaks')
```
Soaking up nulls is similar to Rubys [andand gem](https://rubygems.org/gems/andand), and to the [safe navigation operator](http://docs.groovy-lang.org/latest/html/documentation/index.html#_safe_navigation_operator) in Groovy.
For completeness:
| Example | Definition |
| --- | --- |
| `a?` | tests that `a` is in scope and `a != null` |
| `a ? b` | returns `a` if `a` is in scope and `a != null`; otherwise, `b` |
| `a?.b` or `a?['b']` | returns `a.b` if `a` is in scope and `a != null`; otherwise, `undefined` |
| `a?(b, c)` or `a? b, c`&emsp; | returns the result of calling `a` (with arguments `b` and `c`) if `a` is in scope and callable; otherwise, `undefined` |
| `a ?= b` | assigns the value of `b` to `a` if `a` is not in scope or if `a == null`; produces the new value of `a` |

View file

@ -20,7 +20,7 @@ Things that would otherwise be statements in JavaScript, when used as part of an
codeFor('expressions_comprehension', 'globals')
```
As well as silly things, like passing a **try/catch** statement directly into a function call:
As well as silly things, like passing a `try`/`catch` statement directly into a function call:
```
codeFor('expressions_try', true)

View file

@ -1,4 +1,4 @@
## Function Modifiers
## Bound (Fat Arrow) Functions
In JavaScript, the `this` keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of `this` will be lost. If youre not familiar with this behavior, [this Digital Web article](http://64.13.255.16/articles/scope_in_javascript/) gives a good overview of the quirks.
@ -10,29 +10,4 @@ codeFor('fat_arrow')
If we had used `->` in the callback above, `@customer` would have referred to the undefined “customer” property of the DOM element, and trying to call `purchase()` on it would have raised an exception.
When used in a class definition, methods declared with the fat arrow will be automatically bound to each instance of the class when the instance is constructed.
<div id="generator-functions" class="bookmark"></div>
<div id="async-functions" class="bookmark"></div>
CoffeeScript also supports [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) and [async functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) through the `yield` and `await` keywords respectively. There's no `function*(){}` or `async function(){}` nonsense — a generator in CoffeeScript is simply a function that yields, and an async function in CoffeeScript is simply a function that awaits.
```
codeFor('generators', 'ps.next().value')
```
`yield*` is called `yield from`, and `yield return` may be used if you need to force a generator that doesnt yield.
<div id="generator-iteration" class="bookmark"></div>
You can iterate over a generator function using `for…from`.
```
codeFor('generator_iteration', 'getFibonacciNumbers(10)')
```
Similar to how `yield return` forces a generator, `await return` may be used to force a function to be async.
```
codeFor('async', true)
```
The fat arrow was one of the most popular features of CoffeeScript, and ES2015 [adopted it](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions); so CoffeeScript 2 compiles `=>` to ES `=>`.

View file

@ -0,0 +1,17 @@
## Generator Functions
CoffeeScript supports ES2015 [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) through the `yield` keyword. There's no `function*(){}` nonsense — a generator in CoffeeScript is simply a function that yields.
```
codeFor('generators', 'ps.next().value')
```
`yield*` is called `yield from`, and `yield return` may be used if you need to force a generator that doesnt yield.
<div id="generator-iteration" class="bookmark"></div>
You can iterate over a generator function using `for…from`.
```
codeFor('generator_iteration', 'getFibonacciNumbers(10)')
```

View file

@ -6,10 +6,12 @@ The CoffeeScript compiler takes care to make sure that all of your variables are
codeFor('scope', 'inner')
```
Notice how all of the variable declarations have been pushed up to the top of the closest scope, the first time they appear. **outer** is not redeclared within the inner function, because its already in scope; **inner** within the function, on the other hand, should not be able to change the value of the external variable of the same name, and therefore has a declaration of its own.
Notice how all of the variable declarations have been pushed up to the top of the closest scope, the first time they appear. `outer` is not redeclared within the inner function, because its already in scope; `inner` within the function, on the other hand, should not be able to change the value of the external variable of the same name, and therefore has a declaration of its own.
This behavior is effectively identical to Rubys scope for local variables. Because you dont have direct access to the `var` keyword, its impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that youre not reusing the name of an external variable accidentally, if youre writing a deeply nested function.
Because you dont have direct access to the `var` keyword, its impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that youre not reusing the name of an external variable accidentally, if youre writing a deeply nested function.
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: `(function(){ … })();` This safety wrapper, combined with the automatic generation of the `var` keyword, make it exceedingly difficult to pollute the global namespace by accident.
Although suppressed within this documentation for clarity, all CoffeeScript output (except in files with `import` or `export` statements) is wrapped in an anonymous function: `(function(){ … })();`. This safety wrapper, combined with the automatic generation of the `var` keyword, make it exceedingly difficult to pollute the global namespace by accident. (The safety wrapper can be disabled with the [`bare` option](#usage), and is unnecessary and automatically disabled when using modules.)
If youd like to create top-level variables for other scripts to use, attach them as properties on **window**; attach them as properties on the **exports** object in CommonJS; or use an [`export` statement](#modules). If youre targeting both CommonJS and the browser, the **existential operator** (covered below), gives you a reliable way to figure out where to add them: `exports ? this`
If youd like to create top-level variables for other scripts to use, attach them as properties on `window`; attach them as properties on the `exports` object in CommonJS; or use an [`export` statement](#modules). If youre targeting both CommonJS and the browser, the [existential operator](#existential-operator) (covered below), gives you a reliable way to figure out where to add them: `exports ? this`.
Since CoffeeScript takes care of all variable declaration, it is not possible to declare variables with ES2015s `let` or `const`. [This is intentional](#unsupported-let-const); we feel that the simplicity gained by not having to think about variable declaration outweighs the benefit of having three separate ways to declare variables.

View file

@ -1,12 +1,12 @@
## Loops and Comprehensions
Most of the loops youll write in CoffeeScript will be **comprehensions** over arrays, objects, and ranges. Comprehensions replace (and compile into) **for** loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.
Most of the loops youll write in CoffeeScript will be **comprehensions** over arrays, objects, and ranges. Comprehensions replace (and compile into) `for` loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.
```
codeFor('array_comprehensions')
```
Comprehensions should be able to handle most places where you otherwise would use a loop, **each**/**forEach**, **map**, or **select**/**filter**, for example:<br>
Comprehensions should be able to handle most places where you otherwise would use a loop, `each`/`forEach`, `map`, or `select`/`filter`, for example:<br>
`shortNames = (name for name in list when name.length < 5)`<br>
If you know the start and end of your loop, or would like to step through in fixed-size increments, you can use a range to specify the start and end of your comprehension.
@ -32,13 +32,13 @@ If you would like to iterate over just the keys that are defined on the object i
To iterate a generator function, use `from`. See [Generator Functions](#generator-iteration).
The only low-level loop that CoffeeScript provides is the **while** loop. The main difference from JavaScript is that the **while** loop can be used as an expression, returning an array containing the result of each iteration through the loop.
The only low-level loop that CoffeeScript provides is the `while` loop. The main difference from JavaScript is that the `while` loop can be used as an expression, returning an array containing the result of each iteration through the loop.
```
codeFor('while', 'lyrics.join("\\n")')
```
For readability, the **until** keyword is equivalent to `while not`, and the **loop** keyword is equivalent to `while true`.
For readability, the `until` keyword is equivalent to `while not`, and the `loop` keyword is equivalent to `while true`.
When using a JavaScript loop to generate functions, its common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions dont just share the final values. CoffeeScript provides the `do` keyword, which immediately invokes a passed function, forwarding any arguments.

View file

@ -6,7 +6,7 @@ You can use `not` as an alias for `!`.
For logic, `and` compiles to `&&`, and `or` into `||`.
Instead of a newline or semicolon, `then` can be used to separate conditions from expressions, in **while**, **if**/**else**, and **switch**/**when** statements.
Instead of a newline or semicolon, `then` can be used to separate conditions from expressions, in `while`, `if`/`else`, and `switch`/`when` statements.
As in [YAML](http://yaml.org/), `on` and `yes` are the same as boolean `true`, while `off` and `no` are boolean `false`.
@ -16,6 +16,8 @@ As a shortcut for `this.property`, you can use `@property`.
You can use `in` to test for array presence, and `of` to test for JavaScript object-key presence.
In a `for` loop, `from` compiles to the [ES2015 `of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). (Yes, its unfortunate; the CoffeeScript `of` predates the ES2015 `of`.)
To simplify math expressions, `**` can be used for exponentiation and `//` performs integer division. `%` works just like in JavaScript, while `%%` provides [“dividend dependent modulo”](https://en.wikipedia.org/wiki/Modulo_operation):
```
@ -34,8 +36,9 @@ All together now:
| `true`, `yes`, `on` | `true` |
| `false`, `no`, `off`&emsp; | `false` |
| `@`, `this` | `this` |
| `of` | `in` |
| `in` | _no JS equivalent_ |
| `a in b` | `[].indexOf.call(b, a) >= 0` |
| `a of b` | `a in b` |
| `for a from b` | `for (a of b)` |
| `a ** b` | `Math.pow(a, b)` |
| `a // b` | `Math.floor(a / b)` |
| `a %% b` | `(a % b + b) % b` |

View file

@ -1,6 +1,6 @@
## Splats…
The JavaScript **arguments object** is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats `...`, both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
The JavaScript `arguments` object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats `...`, both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
```
codeFor('splats', true)

View file

@ -1,14 +1,14 @@
## Switch/When/Else
**Switch** statements in JavaScript are a bit awkward. You need to remember to **break** at the end of every **case** statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the `switch` into a returnable, assignable expression. The format is: `switch` condition, `when` clauses, `else` the default case.
`switch` statements in JavaScript are a bit awkward. You need to remember to `break` at the end of every `case` statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the `switch` into a returnable, assignable expression. The format is: `switch` condition, `when` clauses, `else` the default case.
As in Ruby, **switch** statements in CoffeeScript can take multiple values for each **when** clause. If any of the values match, the clause runs.
As in Ruby, `switch` statements in CoffeeScript can take multiple values for each `when` clause. If any of the values match, the clause runs.
```
codeFor('switch')
```
Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.
`switch` statements can also be used without a control expression, turning them in to a cleaner alternative to `if`/`else` chains.
```
codeFor('switch_with_no_expression')

View file

@ -4,4 +4,4 @@ CoffeeScript includes an extensive test suite, which verifies that the compiler
Note that since no JavaScript runtime yet supports ES2015 modules, the tests for module support verify only that the CoffeeScript compilers output is the correct syntax; the tests dont verify that the modules resolve properly.
[Run the tests in your browser.](http://coffeescript.dev/v<%= majorVersion %>/test.html)
[Run the tests in your browser.](http://coffeescript.org/v<%= majorVersion %>/test.html)

View file

@ -1,6 +1,6 @@
## Try/Catch/Finally
Try-expressions have the same semantics as try-statements in JavaScript, though in CoffeeScript, you may omit _both_ the catch and finally parts. The catch part may also omit the error parameter if it is not needed.
`try` expressions have the same semantics as `try` statements in JavaScript, though in CoffeeScript, you may omit _both_ the catch and finally parts. The catch part may also omit the error parameter if it is not needed.
```
codeFor('try')

View file

@ -1,34 +1,3 @@
## Unsupported ECMAScript Features
There are a few ECMAScript features that CoffeeScript intentionally doesnt support.
<section id="unsupported-let-const">
### `let` and `const`: Block-Scoped and Reassignment-Protected Variables
When CoffeeScript was designed, `var` was [intentionally omitted](https://github.com/jashkenas/coffeescript/issues/238#issuecomment-153502). This was to spare developers the mental housekeeping of needing to worry about variable _declaration_ (`var foo`) as opposed to variable _assignment_ (`foo = 1`). The CoffeeScript compiler automatically takes care of declaration for you, by generating `var` statements at the top of every function scope. This makes it impossible to accidentally declare a global variable.
`let` and `const` add a useful ability to JavaScript in that you can use them to declare variables within a _block_ scope, for example within an `if` statement body or a `for` loop body, whereas `var` always declares variables in the scope of an entire function. When CoffeeScript 2 was designed, there was much discussion of whether this functionality was useful enough to outweigh the simplicity offered by never needing to consider variable declaration in CoffeeScript. In the end, it was decided that the simplicity was more valued. In CoffeeScript there remains only one type of variable.
Keep in mind that `const` only protects you from _reassigning_ a variable; it doesnt prevent the variables value from changing, the way constants usually do in other languages:
```js
const obj = {foo: 'bar'};
obj.foo = 'baz'; // Allowed!
obj = {}; // Throws error
```
</section>
<section id="unsupported-get-set">
### `get` and `set` Keyword Shorthand Syntax
`get` and `set`, as keywords preceding functions or class methods, are intentionally unimplemented in CoffeeScript.
This is to avoid grammatical ambiguity, since in CoffeeScript such a construct looks identical to a function call (e.g. `get(function foo() {})`); and because there is an [alternate syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) that is slightly more verbose but just as effective:
```
codeFor('get_set', 'screen.height')
```
</section>

View file

@ -0,0 +1,9 @@
### `get` and `set` keyword shorthand syntax
`get` and `set`, as keywords preceding functions or class methods, are intentionally unimplemented in CoffeeScript.
This is to avoid grammatical ambiguity, since in CoffeeScript such a construct looks identical to a function call (e.g. `get(function foo() {})`); and because there is an [alternate syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) that is slightly more verbose but just as effective:
```
codeFor('get_set', 'screen.height')
```

View file

@ -0,0 +1,13 @@
### `let` and `const`: block-scoped and reassignment-protected variables
When CoffeeScript was designed, `var` was [intentionally omitted](https://github.com/jashkenas/coffeescript/issues/238#issuecomment-153502). This was to spare developers the mental housekeeping of needing to worry about variable _declaration_ (`var foo`) as opposed to variable _assignment_ (`foo = 1`). The CoffeeScript compiler automatically takes care of declaration for you, by generating `var` statements at the top of every function scope. This makes it impossible to accidentally declare a global variable.
`let` and `const` add a useful ability to JavaScript in that you can use them to declare variables within a _block_ scope, for example within an `if` statement body or a `for` loop body, whereas `var` always declares variables in the scope of an entire function. When CoffeeScript 2 was designed, there was much discussion of whether this functionality was useful enough to outweigh the simplicity offered by never needing to consider variable declaration in CoffeeScript. In the end, it was decided that the simplicity was more valued. In CoffeeScript there remains only one type of variable.
Keep in mind that `const` only protects you from _reassigning_ a variable; it doesnt prevent the variables value from changing, the way constants usually do in other languages:
```js
const obj = {foo: 'bar'};
obj.foo = 'baz'; // Allowed!
obj = {}; // Throws error
```

View file

@ -0,0 +1,5 @@
### Named functions and function declarations
Newcomers to CoffeeScript often wonder how to generate the JavaScript `function foo() {}`, as opposed to the `foo = function() {}` that CoffeeScript produces. The first form is a [function declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function), and the second is a [function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function). As stated above, in CoffeeScript [everything is an expression](#expressions), so naturally we favor the expression form. Supporting only one variant helps avoid confusing bugs that can arise from the [subtle differences between the two forms](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Function_declaration_hoisting).
Technically, `foo = function() {}` is creating an anonymous function that gets assigned to a variable named `foo`. Some very early versions of CoffeeScript named this function, e.g. `foo = function foo() {}`, but this was dropped because of compatibility issues with Internet Explorer. For a while this annoyed people, as these functions would be unnamed in stack traces; but modern JavaScript runtimes [infer the names of such anonymous functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) from the names of the variables to which theyre assigned. Given that this is the case, and given that not all functions in function expressions can be named (for example, the functions in `first.fn = ->; second.fn = ->` cant both be named `fn`) its simplest to just preserve the current behavior.

View file

@ -35,3 +35,43 @@ Once installed, you should have access to the `coffee` command, which can execut
`coffee -o lib/ -cw src/`
* Start the CoffeeScript REPL (`Ctrl-D` to exit, `Ctrl-V`for multi-line):<br>
`coffee`
### ES2015+ Output
CoffeeScript 2 outputs the latest ES2015+ syntax. If youre looking for a single tool that takes CoffeeScript input and generates JavaScript output that runs in any JavaScript runtime, assuming you opt out of certain newer features, stick to [CoffeeScript 1.x](/v1/). CoffeeScript 2 [breaks compatibility](#breaking-changes) with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript `=>` becomes an ES `=>`; a CoffeeScript `class` becomes an ES `class`; and so on).
Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibility to either ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like [Babel](http://babeljs.io/), [Rollup](https://github.com/rollup/rollup) or [Traceur Compiler](https://github.com/google/traceur-compiler). In general, [CoffeeScript 2s output is supported as is by Node.js 7.6+](http://node.green/), except for modules which require transpilation.
There are many great task runners for setting up JavaScript build chains, such as [Gulp](http://gulpjs.com/), [Webpack](https://webpack.github.io/), [Grunt](https://gruntjs.com/) and [Broccoli](http://broccolijs.com/). If youre looking for a very minimal solution to get started, you can use [babel-preset-env](https://babeljs.io/docs/plugins/preset-env/) and the command line:
```bash
npm install --global coffeescript@next
npm install --save-dev coffeescript@next babel-cli babel-preset-env
coffee -p *.coffee | babel --presets env > app.js
```
### Node.js
If youd like to use Node.js CommonJS to `require` CoffeeScript files, e.g. `require './app.coffee'`, you must first “register” CoffeeScript as an extension:
```coffee
require 'coffeescript/register'
App = require './app' # The .coffee extension is optional
```
If you want to use the compilers API, for example to make an app that compiles strings of CoffeeScript on the fly, you can `require` the full module:
```coffee
CoffeeScript = require 'coffeescript'
eval CoffeeScript.compile 'console.log "Mmmmm, I could really go for some #{Math.pi}"'
```
The `compile` method has the signature `compile(code, options)` where `code` is a string of CoffeeScript code, and the optional `options` is an object with some or all of the following properties:
* `options.sourceMap`, boolean: if true, a source map will be generated; and instead of returning a string, `compile` will return an object of the form `{js, v3SourceMap, sourceMap}`.
* `options.inlineMap`, boolean: if true, output the source map as a base64-encoded string in a comment at the bottom.
* `options.filename`, string: the filename to use for the source map.
* `options.bare`, boolean: if true, output without the [top-level function safety wrapper](#lexical-scope).
* `options.header`, boolean: if true, output the `Generated by CoffeeScript` header.

View file

@ -64,11 +64,8 @@
<section id="existential-operator">
<%= htmlFor('existential_operator') %>
</section>
<section id="classes">
<%= htmlFor('classes') %>
</section>
<section id="prototypal-inheritance">
<%= htmlFor('prototypal_inheritance') %>
<section id="chaining">
<%= htmlFor('chaining') %>
</section>
<section id="destructuring">
<%= htmlFor('destructuring') %>
@ -76,6 +73,18 @@
<section id="fat-arrow">
<%= htmlFor('fat_arrow') %>
</section>
<section id="generators">
<%= htmlFor('generators') %>
</section>
<section id="async-functions">
<%= htmlFor('async_functions') %>
</section>
<section id="classes">
<%= htmlFor('classes') %>
</section>
<section id="prototypal-inheritance">
<%= htmlFor('prototypal_inheritance') %>
</section>
<section id="switch">
<%= htmlFor('switch') %>
</section>
@ -98,9 +107,6 @@
<%= htmlFor('embedded') %>
</section>
</section>
<section id="unsupported">
<%= htmlFor('unsupported') %>
</section>
<section id="literate">
<%= htmlFor('literate') %>
</section>
@ -134,8 +140,35 @@
<%= htmlFor('contributing') %>
</section>
</section>
<section id="unsupported">
<%= htmlFor('unsupported') %>
<section id="unsupported-let-const">
<%= htmlFor('unsupported_let_const') %>
</section>
<section id="unsupported-named-functions">
<%= htmlFor('unsupported_named_functions') %>
</section>
<section id="unsupported-get-set">
<%= htmlFor('unsupported_get_set') %>
</section>
</section>
<section id="breaking-changes">
<%= htmlFor('breaking_changes') %>
<section id="breaking-changes-default-values">
<%= htmlFor('breaking_changes_default_values') %>
</section>
<section id="breaking-changes-bound-generator-functions">
<%= htmlFor('breaking_changes_bound_generator_functions') %>
</section>
<section id="breaking-changes-classes">
<%= htmlFor('breaking_changes_classes') %>
</section>
<section id="breaking-changes-super-extends">
<%= htmlFor('breaking_changes_super_extends') %>
</section>
<section id="breaking-changes-literate-coffeescript">
<%= htmlFor('breaking_changes_literate_coffeescript') %>
</section>
</section>
<section id="changelog">
<%= htmlFor('changelog') %>

View file

@ -51,18 +51,27 @@
<li class="nav-item">
<a href="#existential-operator" class="nav-link" data-action="sidebar-nav">Existential Operator</a>
</li>
<li class="nav-item">
<a href="#destructuring" class="nav-link" data-action="sidebar-nav">Destructuring Assignment</a>
</li>
<li class="nav-item">
<a href="#chaining" class="nav-link" data-action="sidebar-nav">Chaining Function Calls</a>
</li>
<li class="nav-item">
<a href="#fat-arrow" class="nav-link" data-action="sidebar-nav">Bound (Fat Arrow) Functions</a>
</li>
<li class="nav-item">
<a href="#generators" class="nav-link" data-action="sidebar-nav">Generator Functions</a>
</li>
<li class="nav-item">
<a href="#async-functions" class="nav-link" data-action="sidebar-nav">Async Functions</a>
</li>
<li class="nav-item">
<a href="#classes" class="nav-link" data-action="sidebar-nav">Classes</a>
</li>
<li class="nav-item">
<a href="#prototypal-inheritance" class="nav-link" data-action="sidebar-nav">Prototypal Inheritance</a>
</li>
<li class="nav-item">
<a href="#destructuring" class="nav-link" data-action="sidebar-nav">Destructuring Assignment</a>
</li>
<li class="nav-item">
<a href="#fat-arrow" class="nav-link" data-action="sidebar-nav">Function Modifiers</a>
</li>
<li class="nav-item">
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch and Try/Catch</a>
</li>
@ -81,9 +90,6 @@
<li class="nav-item">
<a href="#embedded" class="nav-link" data-action="sidebar-nav">Embedded JavaScript</a>
</li>
<li class="nav-item">
<a href="#unsupported" class="nav-link" data-action="sidebar-nav">Unsupported ECMAScript Features</a>
</li>
</ul>
</li>
<li class="nav-item">
@ -124,8 +130,39 @@
</li>
</ul>
</li>
<li class="nav-item">
<a href="#unsupported" class="nav-link" data-action="sidebar-nav">Unsupported ECMAScript Features</a>
<ul class="nav">
<li class="nav-item">
<a href="#unsupported-let-const" class="nav-link" data-action="sidebar-nav"><code>let</code> and <code>const</code></a>
</li>
<li class="nav-item">
<a href="#unsupported-named-functions" class="nav-link" data-action="sidebar-nav">Named Functions and Function Declarations</a>
</li>
<li class="nav-item">
<a href="#unsupported-get-set" class="nav-link" data-action="sidebar-nav"><code>get</code> and <code>set</code> Shorthand Syntax</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
<ul class="nav">
<li class="nav-item">
<a href="#breaking-changes-default-values" class="nav-link" data-action="sidebar-nav">Default Values</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-bound-generator-functions" class="nav-link" data-action="sidebar-nav">Bound Generator Functions</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-classes" class="nav-link" data-action="sidebar-nav">Classes</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-super-extends" class="nav-link" data-action="sidebar-nav"><code>super</code> and <code>extends</code></a>
</li>
<li class="nav-item">
<a href="#breaking-changes-literate-coffeescript" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript Parsing</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Change Log</a>