-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update docs for classes, breaking changes (#4438)
* Update classes docs for CS2 * Port breaking changes from https://github.com/jashkenas/coffeescript/wiki/%5BWIP%5D-Breaking-changes-in-CoffeeScript-2 into new docs section * Update browser compiler * Update re @connec’s notes; split classes section into two sections for classes and working with prototypes; make breaking changes examples editable whenever possible
- Loading branch information
1 parent
ef1898b
commit d1d2c16
Showing
15 changed files
with
868 additions
and
495 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 2 additions & 0 deletions
2
documentation/examples/breaking_change_bound_generator_function.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
self = this | ||
f = -> yield self |
3 changes: 3 additions & 0 deletions
3
documentation/examples/breaking_change_function_parameter_default_values.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
f = (a = 1) -> a | ||
|
||
f(null) # Returns 1 in CoffeeScript 1.x, null in CoffeeScript 2 |
4 changes: 4 additions & 0 deletions
4
documentation/examples/breaking_change_super_in_non-class_methods_refactor_with_apply.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
A = -> | ||
B = -> | ||
B extends A | ||
B.prototype.foo = -> A::foo.apply this, arguments |
3 changes: 3 additions & 0 deletions
3
documentation/examples/breaking_change_super_in_non-class_methods_refactor_with_class.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class A | ||
class B extends A | ||
foo: -> super arguments... |
2 changes: 2 additions & 0 deletions
2
documentation/examples/breaking_change_super_with_arguments.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class B extends A | ||
foo: -> super arguments... |
2 changes: 2 additions & 0 deletions
2
documentation/examples/breaking_change_super_without_arguments.coffee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class B extends A | ||
foo: -> super() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class Teenager | ||
@say: (speech) -> | ||
words = speech.split ' ' | ||
fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] | ||
output = [] | ||
for word, index in words | ||
output.push word | ||
output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 | ||
output.join ', ' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
## 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. | ||
|
||
### Function parameter default values | ||
|
||
Per the [ES2015 spec regarding default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters), default values are only applied when a parameter value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the parameter value was `null`. | ||
|
||
``` | ||
codeFor('breaking_change_function_parameter_default_values', 'f(null)') | ||
``` | ||
|
||
### Bound generator functions | ||
|
||
Bound generator functions, a.k.a. generator arrow functions, [aren’t 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') | ||
``` | ||
|
||
### 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`: | ||
|
||
> ```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 can’t be used with `new` (uncommon): | ||
|
||
> ```coffee | ||
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. | ||
|
||
> ```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 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: | ||
|
||
> ```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') | ||
``` | ||
|
||
### 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. | ||
|
||
> ```coffee | ||
class A | ||
name = 'method' | ||
"#{name}": -> # This method will be named 'undefined' | ||
@::[name] = -> # This will work; assigns to `A.prototype.method` | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,15 @@ | ||
## Classes, Inheritance, and Super | ||
## Classes | ||
|
||
JavaScript’s prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript’s prototypes: [Base2](http://code.google.com/p/base2/), [Prototype.js](http://prototypejs.org/), [JS.Class](http://jsclass.jcoglan.com/), etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren’t for a couple of small exceptions: it’s awkward to call **super** (the prototype object’s implementation of the current function), and it’s awkward to correctly set the prototype chain. | ||
|
||
Instead of repetitively attaching functions to a prototype, CoffeeScript provides a basic `class` structure that allows you to name your class, set the superclass, assign prototypal properties, and define the constructor, in a single assignable expression. | ||
|
||
Constructor functions are named, to better support helpful stack traces. In the first class in the example below, `this.constructor.name is "Animal"`. | ||
CoffeeScript 1 provided the `class` and `extends` keywords as syntactic sugar for working with prototypal functions. With ES2015, JavaScript has adopted those keywords; so CoffeeScript 2 compiles its `class` and `extends` keywords to ES2015 classes. | ||
|
||
``` | ||
codeFor('classes', true) | ||
``` | ||
|
||
If structuring your prototypes classically isn’t your cup of tea, CoffeeScript provides a couple of lower-level conveniences. The `extends` operator helps with proper prototype setup, and can be used to create an inheritance chain between any pair of constructor functions; `::` gives you quick access to an object’s prototype; and `super()` is converted into a call against the immediate ancestor’s method of the same name. | ||
Static methods can be defined using `@` before the method name: | ||
|
||
``` | ||
codeFor('prototypes', '"one_two".dasherize()') | ||
codeFor('static', 'Teenager.say("Are we there yet?")') | ||
``` | ||
|
||
Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. Because in the context of a class definition, `this` is the class object itself (the constructor function), you can assign static properties by using | ||
`@property: value`, and call functions defined in parent classes: `@attr 'title', type: 'text'` | ||
Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. In the context of a class definition, `this` is the class object itself; therefore, you can assign static properties by using `@property: value`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## Prototypal Inheritance | ||
|
||
In addition to supporting ES2015 classes, CoffeeScript provides a few shortcuts for working with prototypes. The `extends` operator can be used to create an inheritance chain between any pair of constructor functions, and `::` gives you quick access to an object’s prototype: | ||
|
||
``` | ||
codeFor('prototypes', '"one_two".dasherize()') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters