Merge discussion of CoffeeScript’s benefits into expanded CoffeeScript 2 section and revised Contributing section

This commit is contained in:
Geoffrey Booth 2017-04-02 22:53:18 -07:00
parent b8df321058
commit 27caf62322
6 changed files with 111 additions and 66 deletions

View File

@ -607,6 +607,9 @@ textarea {
<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">
@ -645,6 +648,9 @@ textarea {
<li class="nav-item">
<a href="#annotated-source" class="nav-link" data-action="sidebar-nav">Annotated Source</a>
</li>
<li class="nav-item">
<a href="#contributing" class="nav-link" data-action="sidebar-nav">Contributing</a>
</li>
</ul>
</li>
<li class="nav-item">
@ -763,8 +769,15 @@ cubes = (function() {
</section>
<section id="coffeescript-2">
<h2>CoffeeScript 2</h2><p>CoffeeScript 2 generates JavaScript that uses the latest ES2015+ features. It is your responsibility to ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like <a href="http://babeljs.io/">Babel</a>, <a href="https://github.com/rollup/rollup">Rollup</a> or <a href="https://github.com/google/traceur-compiler">Traceur Compiler</a>. In general, <a href="http://node.green/">CoffeeScript 2s output is fully supported by Node.js 7+</a>, although async functions require the <code>--harmony</code> or <code>--harmony-async-await</code> flags; and ES2015 modules require an additional transpiler. Output JavaScript intended for browsers generally requires additional transpilation.</p>
<p>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 <a href="v1/">CoffeeScript 1.x branch</a>. CoffeeScript 2 <a href="#breaking-changes">breaks compatibility</a> with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript <code>=&gt;</code> becomes an ES <code>=&gt;</code>; a CoffeeScript <code>class</code> becomes an ES <code>class</code>; and so on).</p>
<h2>CoffeeScript 2</h2><h3>Why CoffeeScript When Theres ES2015+?</h3><p>CoffeeScript introduced many new features to the JavaScript world, such as <a href="#fat-arrow"><code>=&gt;</code></a> and <a href="#destructuring">destructuring</a> and <a href="#classes">classes</a>. We are happy that ECMA has seen their utility and adopted them into ECMAScript.</p>
<p>CoffeeScripts intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been <em>simplicity:</em> 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.</p>
<h3>ES2015+ Output</h3><p>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 <a href="v1/">CoffeeScript 1.x branch</a>. CoffeeScript 2 <a href="#breaking-changes">breaks compatibility</a> with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript <code>=&gt;</code> becomes an ES <code>=&gt;</code>; a CoffeeScript <code>class</code> becomes an ES <code>class</code>; and so on).</p>
<p>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 <a href="http://babeljs.io/">Babel</a>, <a href="https://github.com/rollup/rollup">Rollup</a> or <a href="https://github.com/google/traceur-compiler">Traceur Compiler</a>. In general, <a href="http://node.green/">CoffeeScript 2s output is supported as is by Node.js 7.6+</a>, except for modules which require transpilation.</p>
<p>There are many great task runners for setting up JavaScript build chains, such as <a href="http://gulpjs.com/">Gulp</a>, <a href="https://webpack.github.io/">Webpack</a>, <a href="https://gruntjs.com/">Grunt</a> and <a href="http://broccolijs.com/">Broccoli</a>. If youre looking for a very minimal solution to get started, you can use <a href="https://babeljs.io/docs/plugins/preset-env/">babel-preset-env</a> and the command line:</p>
<blockquote>
<pre><code>npm install --global coffeescript@next
npm install --save-dev coffeescript@next babel-cli babel-preset-env
coffee -p *.coffee | babel --presets env > app.js</code></pre></blockquote>
</section>
<section id="installation">
@ -2994,6 +3007,60 @@ function time() {
</section>
</section>
<section id="unsupported">
<h2>Unsupported ECMAScript Features</h2><p>There are a few ECMAScript features that CoffeeScript intentionally doesnt support.</p>
<h3><code>let</code> and <code>const</code>: Block-Scoped and Reassignment-Protected Variables</h3><p>When CoffeeScript was designed, <code>var</code> was <a href="https://github.com/jashkenas/coffeescript/issues/238#issuecomment-153502">intentionally omitted</a>. This was to spare developers the mental housekeeping of needing to worry about variable <em>declaration</em> (<code>var foo</code>) as opposed to variable <em>assignment</em> (<code>foo = 1</code>). The CoffeeScript compiler automatically takes care of declaration for you, by generating <code>var</code> statements at the top of every function scope. This makes it impossible to accidentally declare a global variable.</p>
<p><code>let</code> and <code>const</code> add a useful ability to JavaScript in that you can use them to declare variables within a <em>block</em> scope, for example within an <code>if</code> statement body or a <code>for</code> loop body, whereas <code>var</code> 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.</p>
<p>Keep in mind that <code>const</code> only protects you from <em>reassigning</em> a variable; it doesnt prevent the variables value from changing, the way constants usually do in other languages:</p>
<blockquote>
<pre><code>const obj = {foo: 'bar'};
obj.foo = 'baz'; // Allowed!
obj = {}; // Throws error</code></pre></blockquote>
<h3><code>get</code> and <code>set</code> Keyword Shorthand Syntax</h3><p><code>get</code> and <code>set</code>, as keywords preceding functions or class methods, are intentionally unimplemented in CoffeeScript.</p>
<p>This is to avoid grammatical ambiguity, since in CoffeeScript such a construct looks identical to a function call (e.g. <code>get(function foo() {})</code>); and because there is an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">alternate syntax</a> that is slightly more verbose but just as effective:</p>
<aside class="code-example container-fluid bg-ribbed-dark" data-example="get_set">
<div class="row">
<div class="col-md-6 coffeescript-input-column">
<textarea class="coffeescript-input" id="get_set-coffee">screen =
width: 1200
ratio: 16/9
Object.defineProperty screen, 'height',
get: ->
this.width / this.ratio
set: (val) ->
this.width = val / this.ratio
</textarea>
</div>
<div class="col-md-6 javascript-output-column">
<textarea class="javascript-output" id="get_set-js">var screen;
screen = {
width: 1200,
ratio: 16 / 9
};
Object.defineProperty(screen, 'height', {
get: function() {
return this.width / this.ratio;
},
set: function(val) {
return this.width = val / this.ratio;
}
});
</textarea>
</div>
</div>
<div class="row">
<div class="col-xs-12 text-xs-right">
<button type="button" class="btn btn-primary" data-action="run-code-example" data-example="get_set" data-run="screen.height"><small></small>&ensp;screen.height</button>
</div>
</div>
</aside>
</section>
<section id="breaking-changes">
<h2>Breaking Changes From CoffeeScript 1.x to 2</h2><p>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.</p>
<h3>Function parameter default values</h3><p>Per the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">ES2015 spec regarding default parameters</a>, default values are only applied when a parameter value is missing or <code>undefined</code>. In CoffeeScript 1.x, the default value would be applied in those cases but also if the parameter value was <code>null</code>.</p>
@ -3306,6 +3373,20 @@ The CoffeeScript logo is available in SVG for use in presentations.</li>
<li><a href="http://coffeescript.org/v2/annotated-source/sourcemap.html">Source Maps — src/sourcemap</a></li>
</ul>
</section>
<section id="contributing">
<h2>Contributing</h2><p>Contributions are welcome! Feel free to fork <a href="http://github.com/jashkenas/coffeescript">the repo</a> and submit a pull request.</p>
<p><a href="#unsupported">Some features of ECMAScript are intentionally unsupported</a>. Please review both the open and closed <a href="http://github.com/jashkenas/coffeescript/issues">issues on GitHub</a> to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the proposal approval process).</p>
<p>For more resources on adding to CoffeeScript, please see <a href="https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler">the Wiki</a>, especially <a href="https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works">How The Parser Works</a>.</p>
<p>There are several things you can do to increase your odds of having your pull request accepted:</p>
<ul>
<li>Create tests! Any pull request should probably include basic tests to verify you didnt break anything, or future changes wont break your code.</li>
<li>Follow the style of the rest of the CoffeeScript codebase.</li>
<li>Ensure any ECMAScript syntax is mature (at Stage 4), with no further potential changes.</li>
<li>Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.</li>
</ul>
<p>Of course, its entirely possible that you have a great addition, but it doesnt fit within these constraints. Feel free to roll your own solution; you will have <a href="https://github.com/jashkenas/coffeescript/wiki/In-The-Wild">plenty of company</a>.</p>
</section>
</section>
<section id="changelog">

View File

@ -1,5 +1,21 @@
## CoffeeScript 2
CoffeeScript 2 generates JavaScript that uses the latest ES2015+ features. It is your responsibility to 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 fully supported by Node.js 7+](http://node.green/), although async functions require the `--harmony` or `--harmony-async-await` flags; and ES2015 modules require an additional transpiler. Output JavaScript intended for browsers generally requires additional transpilation.
### Why CoffeeScript When Theres ES2015+?
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).
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
```

View File

@ -1,21 +1,16 @@
## Contributing
Contributions are welcome, feel free to fork a copy and submit a pull request.
## Contributing
If there is a core part of ECMAScript you think we are missing, head on over to [CoffeeScript issues on GitHub](http://github.com/jashkenas/coffeescript/issues), and dig around in the open and closed issues.
Contributions are welcome! Feel free to fork [the repo](http://github.com/jashkenas/coffeescript) and submit a pull request.
For more resources on adding to CoffeeScript, please see [the Wiki](https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler) or [How The Parser Works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works) if you are interested in learning how the parser works.
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](http://github.com/jashkenas/coffeescript/issues) to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the proposal approval process).
There are several things you can do to increase your odds of having the pull request accepted:
For more resources on adding to CoffeeScript, please see [the Wiki](https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler), especially [How The Parser Works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works).
* Create tests! Any pull request should probably include basic tests to verify you didn't break anything, or future changes won't break your code.
* Follow the CoffeeScript style guide
* Ensure any ECMAScript addition is mature (at Stage 4), with no further potential syntax changes.
* Adding only the features that help the community rather than a specific use case.
There are several things you can do to increase your odds of having your pull request accepted:
Of course, it's entirely possible that you have a great addition, but it doesn't fit directly with the CoffeeScript code base.
* Create tests! Any pull request should probably include basic tests to verify you didnt break anything, or future changes wont break your code.
* Follow the style of the rest of the CoffeeScript codebase.
* Ensure any ECMAScript syntax is mature (at Stage 4), with no further potential changes.
* Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.
This might be the time to...
## Roll Your Own
You are of course, welcome to fork the language and add in the features you want. There are [quite a few](https://github.com/jashkenas/coffeescript/wiki/In-The-Wild) really interesting projects that have done so, and more are welcome.
Of course, its entirely possible that you have a great addition, but it doesnt fit within these constraints. Feel free to roll your own solution; you will have [plenty of company](https://github.com/jashkenas/coffeescript/wiki/In-The-Wild).

View File

@ -1,43 +0,0 @@
## Why CoffeeScript?
There are a few things you should know about CoffeeScript.
CoffeeScript is about:
* Reducing complexity
* Keeping your code clean
* Being terse
* Removing as many 'Bad Parts' as possible
* Reducing code quality issues
* Increasing readability
* Being stable
* Bringing out the best from ECMAScript
CoffeeScript is NOT about:
* Having the latest XX/YY feature
* Implementing every aspect of ECMAScript, just because it's there.
* Trying to appease developers from other languages
There are many style choices within the language, and they have been carefully thought out. Taking time out to understand how CoffeeScript works, and how to work well with it will help you write better, easier to read, safer and more reliable code.
## Why not just use ECMAScript 7?
ECMAScript has adopted much of the syntax and ideas of CoffeeScript. Unfortunately it still exposes you to many of the 'Bad Parts' of the language. On top of that the ECMASCript syntax is cumulative, allowing a much larger spectrum of potential errors.
ECMAScript 6/7 are standards, and you should probably know how to work with it. You might assume that working with ECMAScript 6 is more direct or cleaner. But using those newer features still requires a transpiler, for instance Babel. If you consider most front end targetted code still needs a build tool like Grunt, then you will find adding an extra step for CoffeeScript very trivial.
You will find:
* CoffeeScript has adopted the vast majority of stable ECMAScript features.
* CoffeeScript protects you by avoiding a wide spectrum of errors.
* You have consistent variable behavior without having to think about context and usage of every variable.
* You reduce cognitive load of the syntax and can get down to solving problems.
* Most parentheses are optional, making functional programming styles much cleaner.
* CoffeeScript forces indenting, which makes code much more readable, and eliminates many nesting errors.
* Most Parentheses go away and no more semicolan errors.
* CoffeeScript has an existential operator `?`, which makes checking for missing elements a breeze.
* CoffeeScript is fully interoperable with ECMAScript code.
* Cleaner syntax for yields, async, and unbound functions `() ->`
You can learn CoffeeScript in a few hours, and you will be amazed at how much better your code will be.

View File

@ -16,7 +16,6 @@
<section id="overview">
<%= htmlFor('introduction') %>
<%= htmlFor('overview') %>
<%= htmlFor('why_coffeescript') %>
</section>
<section id="coffeescript-2">
<%= htmlFor('coffeescript_2') %>

View File

@ -3,9 +3,6 @@
<li class="nav-item">
<a href="#top" class="nav-link" data-action="sidebar-nav">Overview</a>
</li>
<li class="nav-item">
<a href="#top" class="nav-link" data-action="sidebar-nav">Why CoffeeScript</a>
</li>
<li class="nav-item">
<a href="#coffeescript-2" class="nav-link" data-action="sidebar-nav">CoffeeScript 2</a>
</li>