
* Update package versions; remove marked * Revise docs to use Markdown-It: tables are now GitHub-Flavored Markdown tables, avoid hack of blockquoted code blocks * Add anchors for sub-sections * Add syntax highlighting to uneducable code blocks; fix missing italics variant for comments font * Update docs about breaking changes in Literate CoffeeScript, move Breaking Changes section below Literate CoffeeScript section * Update docs regarding destructuring default values breaking change * Update changelog, with spitball release date for beta1 * Fix highlight function return statement
4.9 KiB
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.
Default values for function parameters and destructured elements
Per the ES2015 spec regarding function default parameters and destructuring 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')
Bound generator functions
Bound generator functions, a.k.a. generator arrow functions, aren’t allowed in ECMAScript. You can write function*
or =>
, but not both. Therefore, CoffeeScript code like this:
f = => yield this
# Throws a compiler error
Needs to be rewritten the old-fashioned way:
codeFor('breaking_change_bound_generator_function')
Classes are compiled to ES2015 classes
ES2015 classes and their methods have some restrictions beyond those on regular functions.
Class constructors can’t be invoked without new
:
(class)()
# Throws a TypeError at runtime
Derived (extended) class constructor
s cannot use this
before calling super
:
class B extends A
constructor: -> this
# Throws a compiler error
Class methods can’t be used with new
(uncommon):
class Namespace
@Klass = ->
new Namespace.Klass
# Throws a TypeError at runtime
Bare super
Due to a syntax clash with super
with accessors, bare super
no longer compiles to a super call forwarding all arguments.
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 doesn’t require arguments, just call super()
:
codeFor('breaking_change_super_without_arguments')
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:
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')
Dynamic class keys exclude executable class scope
Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods can’t use values from the executable class body unless the methods are assigned in prototype style.
class A
name = 'method'
"#{name}": -> # This method will be named 'undefined'
@::[name] = -> # This will work; assigns to `A.prototype.method`
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 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 code’s “left margin,” with all code in the file relative to that column.