/index.html
http://github.com/jashkenas/coffee-script · HTML · 3694 lines · 3274 code · 420 blank · 0 comment · 0 complexity · 937a7822ad1ff30897820ca398114b4a MD5 · raw file
Large files are truncated click here to view the full file
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
- <title>CoffeeScript</title>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <link rel="canonical" href="http://coffeescript.org" />
- <link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
- <link rel="stylesheet" type="text/css" href="documentation/css/tomorrow.css" />
- <link rel="shortcut icon" href="documentation/images/favicon.ico" />
- </head>
- <body>
- <div id="fadeout"></div>
- <div id="flybar">
- <a id="logo" href="#top"><img src="documentation/images/logo.png" width="225" height="39" alt="CoffeeScript" /></a>
- <div class="navigation toc">
- <div class="button">
- Table of Contents
- </div>
- <div class="contents menu">
- <a href="#overview">Overview</a>
- <a href="#installation">Installation</a>
- <a href="#usage">Usage</a>
- <a href="#literate">Literate CoffeeScript</a>
- <a href="#language">Language Reference</a>
- <a href="#literals">Literals: Functions, Objects and Arrays</a>
- <a href="#lexical-scope">Lexical Scoping and Variable Safety</a>
- <a href="#conditionals">If, Else, Unless, and Conditional Assignment</a>
- <a href="#splats">Splats...</a>
- <a href="#loops">Loops and Comprehensions</a>
- <a href="#slices">Array Slicing and Splicing</a>
- <a href="#expressions">Everything is an Expression</a>
- <a href="#operators">Operators and Aliases</a>
- <a href="#classes">Classes, Inheritance, and Super</a>
- <a href="#destructuring">Destructuring Assignment</a>
- <a href="#fat-arrow">Bound and Generator Functions</a>
- <a href="#embedded">Embedded JavaScript</a>
- <a href="#switch">Switch and Try/Catch</a>
- <a href="#comparisons">Chained Comparisons</a>
- <a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
- <a href="#regexes">Block Regular Expressions</a>
- <a href="#cake">Cake, and Cakefiles</a>
- <a href="#source-maps">Source Maps</a>
- <a href="#scripts">"text/coffeescript" Script Tags</a>
- <a href="#resources">Books, Screencasts, Examples and Resources</a>
- <a href="#changelog">Change Log</a>
- </div>
- </div>
- <div class="navigation try">
- <div class="button">
- Try CoffeeScript
- <div class="repl_bridge"></div>
- </div>
- <div class="contents repl_wrapper">
- <div class="code">
- <div class="screenshadow tl"></div>
- <div class="screenshadow tr"></div>
- <div class="screenshadow bl"></div>
- <div class="screenshadow br"></div>
- <div id="repl_source_wrap">
- <textarea id="repl_source" rows="100" spellcheck="false">alert "Hello CoffeeScript!"</textarea>
- </div>
- <div id="repl_results_wrap"><pre id="repl_results"></pre></div>
- <div class="minibutton dark run" title="Ctrl-Enter">Run</div>
- <a class="minibutton permalink" id="repl_permalink">Link</a>
- <br class="clear" />
- </div>
- </div>
- </div>
- <div class="navigation annotated">
- <div class="button">
- Annotated Source
- </div>
- <div class="contents menu">
- <a href="documentation/docs/grammar.html">Grammar Rules — src/grammar</a>
- <a href="documentation/docs/lexer.html">Lexing Tokens — src/lexer</a>
- <a href="documentation/docs/rewriter.html">The Rewriter — src/rewriter</a>
- <a href="documentation/docs/nodes.html">The Syntax Tree — src/nodes</a>
- <a href="documentation/docs/scope.html">Lexical Scope — src/scope</a>
- <a href="documentation/docs/helpers.html">Helpers & Utility Functions — src/helpers</a>
- <a href="documentation/docs/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
- <a href="documentation/docs/cake.html">Cake & Cakefiles — src/cake</a>
- <a href="documentation/docs/command.html">"coffee" Command-Line Utility — src/command</a>
- <a href="documentation/docs/optparse.html">Option Parsing — src/optparse</a>
- <a href="documentation/docs/repl.html">Interactive REPL — src/repl</a>
- <a href="documentation/docs/sourcemap.html">Source Maps — src/sourcemap</a>
- </div>
- </div>
- </div>
- <div class="container">
- <span class="bookmark" id="top"></span>
- <p>
- <b>CoffeeScript is a little language that compiles into JavaScript.</b>
- Underneath that awkward Java-esque patina, JavaScript has always had
- a gorgeous heart. CoffeeScript is an attempt to expose
- the good parts of JavaScript in a simple way.
- </p>
- <p>
- The golden rule of CoffeeScript is: <i>"It's just JavaScript"</i>. The code
- compiles one-to-one into the equivalent JS, and there is
- no interpretation at runtime. You can use any existing JavaScript library
- seamlessly from CoffeeScript (and vice-versa). The compiled output is
- readable and pretty-printed, will work in every JavaScript runtime, and tends
- to run as fast or faster than the equivalent handwritten JavaScript.
- </p>
- <p>
- <b>Latest Version:</b>
- <a href="http://github.com/jashkenas/coffeescript/tarball/1.10.0">1.10.0</a>
- </p>
- <pre>npm install -g coffee-script</pre>
- <h2>
- <span id="overview" class="bookmark"></span>
- Overview
- </h2>
- <p><i>CoffeeScript on the left, compiled JavaScript output on the right.</i></p>
- <div class='code'><pre><code><span class="comment"># Assignment:</span>
- number = <span class="number">42</span>
- opposite = <span class="literal">true</span>
- <span class="comment"># Conditions:</span>
- number = -<span class="number">42</span> <span class="keyword">if</span> opposite
- <span class="comment"># Functions:</span>
- <span class="function"><span class="title">square</span> = <span class="params">(x)</span> -></span> x * x
- <span class="comment"># Arrays:</span>
- list = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]
- <span class="comment"># Objects:</span>
- math =
- <span class="attribute">root</span>: Math.sqrt
- <span class="attribute">square</span>: square
- <span class="attribute">cube</span>: <span class="function"><span class="params">(x)</span> -></span> x * square x
- <span class="comment"># Splats:</span>
- <span class="function"><span class="title">race</span> = <span class="params">(winner, runners...)</span> -></span>
- <span class="built_in">print</span> winner, runners
- <span class="comment"># Existence:</span>
- alert <span class="string">"I knew it!"</span> <span class="keyword">if</span> elvis?
- <span class="comment"># Array comprehensions:</span>
- cubes = (math.cube num <span class="keyword">for</span> num <span class="keyword">in</span> list)
- </code></pre><pre><code><span class="keyword">var</span> cubes, list, math, num, number, opposite, race, square,
- slice = [].slice;
- number = <span class="number">42</span>;
- opposite = <span class="literal">true</span>;
- <span class="keyword">if</span> (opposite) {
- number = -<span class="number">42</span>;
- }
- square = <span class="function"><span class="keyword">function</span><span class="params">(x)</span> {</span>
- <span class="keyword">return</span> x * x;
- };
- list = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];
- math = {
- root: <span class="built_in">Math</span>.sqrt,
- square: square,
- cube: <span class="function"><span class="keyword">function</span><span class="params">(x)</span> {</span>
- <span class="keyword">return</span> x * square(x);
- }
- };
- race = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> runners, winner;
- winner = <span class="built_in">arguments</span>[<span class="number">0</span>], runners = <span class="number">2</span> <= <span class="built_in">arguments</span>.length ? slice.call(<span class="built_in">arguments</span>, <span class="number">1</span>) : [];
- <span class="keyword">return</span> print(winner, runners);
- };
- <span class="keyword">if</span> (<span class="keyword">typeof</span> elvis !== <span class="string">"undefined"</span> && elvis !== <span class="literal">null</span>) {
- alert(<span class="string">"I knew it!"</span>);
- }
- cubes = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> i, len, results;
- results = [];
- <span class="keyword">for</span> (i = <span class="number">0</span>, len = list.length; i < len; i++) {
- num = list[i];
- results.push(math.cube(num));
- }
- <span class="keyword">return</span> results;
- })();
- </code></pre><script>window.example1 = "# Assignment:\nnumber = 42\nopposite = true\n\n# Conditions:\nnumber = -42 if opposite\n\n# Functions:\nsquare = (x) -> x * x\n\n# Arrays:\nlist = [1, 2, 3, 4, 5]\n\n# Objects:\nmath =\n root: Math.sqrt\n square: square\n cube: (x) -> x * square x\n\n# Splats:\nrace = (winner, runners...) ->\n print winner, runners\n\n# Existence:\nalert \"I knew it!\" if elvis?\n\n# Array comprehensions:\ncubes = (math.cube num for num in list)\n"</script><div class='minibutton ok' onclick='javascript: var cubes, list, math, num, number, opposite, race, square,
- slice = [].slice;
- number = 42;
- opposite = true;
- if (opposite) {
- number = -42;
- }
- square = function(x) {
- return x * x;
- };
- list = [1, 2, 3, 4, 5];
- math = {
- root: Math.sqrt,
- square: square,
- cube: function(x) {
- return x * square(x);
- }
- };
- race = function() {
- var runners, winner;
- winner = arguments[0], runners = 2 <= arguments.length ? slice.call(arguments, 1) : [];
- return print(winner, runners);
- };
- if (typeof elvis !== "undefined" && elvis !== null) {
- alert("I knew it!");
- }
- cubes = (function() {
- var i, len, results;
- results = [];
- for (i = 0, len = list.length; i < len; i++) {
- num = list[i];
- results.push(math.cube(num));
- }
- return results;
- })();
- ;alert(cubes);'>run: cubes</div><br class='clear' /></div>
- <h2>
- <span id="installation" class="bookmark"></span>
- Installation
- </h2>
- <p>
- The CoffeeScript compiler is itself
- <a href="documentation/docs/grammar.html">written in CoffeeScript</a>,
- using the <a href="http://jison.org">Jison parser generator</a>. The
- command-line version of <code>coffee</code> is available as a
- <a href="http://nodejs.org/">Node.js</a> utility. The
- <a href="extras/coffee-script.js">core compiler</a> however, does not
- depend on Node, and can be run in any JavaScript environment, or in the
- browser (see "Try CoffeeScript", above).
- </p>
- <p>
- To install, first make sure you have a working copy of the latest stable version of
- <a href="http://nodejs.org/">Node.js</a>. You can then install CoffeeScript globally
- with <a href="http://npmjs.org">npm</a>:
- </p>
- <pre>
- npm install -g coffee-script</pre>
- <p>
- When you need CoffeeScript as a dependency, install it locally:
- </p>
- <pre>
- npm install --save coffee-script</pre>
- <p>
- If you'd prefer to install the latest <b>master</b> version of CoffeeScript, you
- can clone the CoffeeScript
- <a href="http://github.com/jashkenas/coffeescript">source repository</a>
- from GitHub, or download
- <a href="http://github.com/jashkenas/coffeescript/tarball/master">the source</a> directly.
- To install the latest master CoffeeScript compiler with npm:
- </p>
- <pre>
- npm install -g jashkenas/coffeescript</pre>
- <p>
- Or, if you want to install to <code>/usr/local</code>, and don't want to use
- npm to manage it, open the <code>coffee-script</code> directory and run:
- </p>
- <pre>
- sudo bin/cake install</pre>
- <h2>
- <span id="usage" class="bookmark"></span>
- Usage
- </h2>
- <p>
- Once installed, you should have access to the <code>coffee</code> command,
- which can execute scripts, compile <code>.coffee</code> files into <code>.js</code>,
- and provide an interactive REPL. The <code>coffee</code> command takes the
- following options:
- </p>
- <table>
- <tr>
- <td><code>-c, --compile</code></td>
- <td>
- Compile a <code>.coffee</code> script into a <code>.js</code> JavaScript file
- of the same name.
- </td>
- </tr>
- <tr>
- <td><code>-m, --map</code></td>
- <td>
- Generate source maps alongside the compiled JavaScript files. Adds
- <code>sourceMappingURL</code> directives to the JavaScript as well.
- </td>
- </tr>
- <tr>
- <td width="25%"><code>-i, --interactive</code></td>
- <td>
- Launch an interactive CoffeeScript session to try short snippets.
- Identical to calling <code>coffee</code> with no arguments.
- </td>
- </tr>
- <tr>
- <td><code>-o, --output [DIR]</code></td>
- <td>
- Write out all compiled JavaScript files into the specified directory.
- Use in conjunction with <code>--compile</code> or <code>--watch</code>.
- </td>
- </tr>
- <tr>
- <td><code>-j, --join [FILE]</code></td>
- <td>
- Before compiling, concatenate all scripts together in the order they
- were passed, and write them into the specified file.
- Useful for building large projects.
- </td>
- </tr>
- <tr>
- <td><code>-w, --watch</code></td>
- <td>
- Watch files for changes, rerunning the specified command when any
- file is updated.
- </td>
- </tr>
- <tr>
- <td><code>-p, --print</code></td>
- <td>
- Instead of writing out the JavaScript as a file, print it
- directly to <b>stdout</b>.
- </td>
- </tr>
- <tr>
- <td><code>-s, --stdio</code></td>
- <td>
- Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT.
- Good for use with processes written in other languages. An example:<br />
- <code>cat src/cake.coffee | coffee -sc</code>
- </td>
- </tr>
- <tr>
- <td><code>-l, --literate</code></td>
- <td>
- Parses the code as Literate CoffeeScript. You only need to specify
- this when passing in code directly over <b>stdio</b>, or using some sort
- of extension-less file name.
- </td>
- </tr>
- <tr>
- <td><code>-e, --eval</code></td>
- <td>
- Compile and print a little snippet of CoffeeScript directly from the
- command line. For example:<br /><code>coffee -e "console.log num for num in [10..1]"</code>
- </td>
- </tr>
- <tr>
- <td><code>-b, --bare</code></td>
- <td>
- Compile the JavaScript without the
- <a href="#lexical-scope">top-level function safety wrapper</a>.
- </td>
- </tr>
- <tr>
- <td><code>-t, --tokens</code></td>
- <td>
- Instead of parsing the CoffeeScript, just lex it, and print out the
- token stream: <code>[IDENTIFIER square] [ASSIGN =] [PARAM_START (]</code> ...
- </td>
- </tr>
- <tr>
- <td><code>-n, --nodes</code></td>
- <td>
- Instead of compiling the CoffeeScript, just lex and parse it, and print
- out the parse tree:
- <pre class="no_bar">
- Expressions
- Assign
- Value "square"
- Code "x"
- Op *
- Value "x"
- Value "x"</pre>
- </td>
- </tr>
- <tr>
- <td><code>--nodejs</code></td>
- <td>
- The <code>node</code> executable has some useful options you can set,
- such as<br /> <code>--debug</code>, <code>--debug-brk</code>, <code>--max-stack-size</code>,
- and <code>--expose-gc</code>. Use this flag to forward options directly to Node.js.
- To pass multiple flags, use <code>--nodejs</code> multiple times.
- </td>
- </tr>
- </table>
- <p>
- <b>Examples:</b>
- </p>
- <ul>
- <li>
- Compile a directory tree of <code>.coffee</code> files in <code>src</code> into a parallel
- tree of <code>.js</code> files in <code>lib</code>:<br />
- <code>coffee --compile --output lib/ src/</code>
- </li>
- <li>
- Watch a file for changes, and recompile it every time the file is saved:<br />
- <code>coffee --watch --compile experimental.coffee</code>
- </li>
- <li>
- Concatenate a list of files into a single script:<br />
- <code>coffee --join project.js --compile src/*.coffee</code>
- </li>
- <li>
- Print out the compiled JS from a one-liner:<br />
- <code>coffee -bpe "alert i for i in [0..10]"</code>
- </li>
- <li>
- All together now, watch and recompile an entire project as you work on it:<br />
- <code>coffee -o lib/ -cw src/</code>
- </li>
- <li>
- Start the CoffeeScript REPL (<code>Ctrl-D</code> to exit, <code>Ctrl-V</code>for multi-line):<br />
- <code>coffee</code>
- </li>
- </ul>
- <h2>
- <span id="literate" class="bookmark"></span>
- Literate CoffeeScript
- </h2>
- <p>
- Besides being used as an ordinary programming language, CoffeeScript may
- also be written in "literate" mode. If you name your file with a
- <code>.litcoffee</code> extension, you can write it as a Markdown document —
- a document that also happens to be executable CoffeeScript code. The compiler
- will treat any indented blocks (Markdown's way of indicating source code)
- as code, and ignore the rest as comments.
- </p>
- <p>
- Just for kicks, a little bit of the compiler is currently implemented in this fashion:
- See it
- <a href="https://gist.github.com/jashkenas/3fc3c1a8b1009c00d9df">as a document</a>,
- <a href="https://raw.github.com/jashkenas/coffeescript/master/src/scope.litcoffee">raw</a>,
- and <a href="http://cl.ly/LxEu">properly highlighted in a text editor</a>.
- </p>
- <p>
- I'm fairly excited about this direction for the language, and am looking
- forward to writing (and more importantly, reading) more programs in this style.
- More information about Literate CoffeeScript, including an
- <a href="https://github.com/jashkenas/journo">example program</a>,
- are <a href="http://ashkenas.com/literate-coffeescript">available in this blog post</a>.
- </p>
- <h2>
- <span id="language" class="bookmark"></span>
- Language Reference
- </h2>
- <p>
- <i>
- This reference is structured so that it can be read from top to bottom,
- if you like. Later sections use ideas and syntax previously introduced.
- Familiarity with JavaScript is assumed.
- In all of the following examples, the source CoffeeScript is provided on
- the left, and the direct compilation into JavaScript is on the right.
- </i>
- </p>
- <p>
- <i>
- Many of the examples can be run (where it makes sense) by pressing the <b>run</b>
- button on the right, and can be loaded into the "Try CoffeeScript"
- console by pressing the <b>load</b> button on the left.
- </i>
- <p>
- First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code.
- You don't need to use semicolons <code>;</code> to terminate expressions,
- ending the line will do just as well (although semicolons can still
- be used to fit multiple expressions onto a single line).
- Instead of using curly braces
- <code>{ }</code> to surround blocks of code in <a href="#literals">functions</a>,
- <a href="#conditionals">if-statements</a>,
- <a href="#switch">switch</a>, and <a href="#try">try/catch</a>,
- use indentation.
- </p>
- <p>
- You don't need to use parentheses to invoke a function if you're passing
- arguments. The implicit call wraps forward to the end of the line or block expression.<br />
- <code>console.log sys.inspect object</code> → <code>console.log(sys.inspect(object));</code>
- </p>
- <p>
- <span id="literals" class="bookmark"></span>
- <b class="header">Functions</b>
- Functions are defined by an optional list of parameters in parentheses,
- an arrow, and the function body. The empty function looks like this:
- <code>-></code>
- </p>
- <div class='code'><pre><code><span class="function"><span class="title">square</span> = <span class="params">(x)</span> -></span> x * x
- <span class="function"><span class="title">cube</span> = <span class="params">(x)</span> -></span> square(x) * x
- </code></pre><pre><code><span class="keyword">var</span> cube, square;
- square = <span class="function"><span class="keyword">function</span><span class="params">(x)</span> {</span>
- <span class="keyword">return</span> x * x;
- };
- cube = <span class="function"><span class="keyword">function</span><span class="params">(x)</span> {</span>
- <span class="keyword">return</span> square(x) * x;
- };
- </code></pre><script>window.example2 = "square = (x) -> x * x\ncube = (x) -> square(x) * x\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example2);'>load</div><div class='minibutton ok' onclick='javascript: var cube, square;
- square = function(x) {
- return x * x;
- };
- cube = function(x) {
- return square(x) * x;
- };
- ;alert(cube(5));'>run: cube(5)</div><br class='clear' /></div>
- <p>
- Functions may also have default values for arguments, which will be used
- if the incoming argument is missing (<code>null</code> or <code>undefined</code>).
- </p>
- <div class='code'><pre><code><span class="function"><span class="title">fill</span> = <span class="params">(container, liquid = <span class="string">"coffee"</span>)</span> -></span>
- <span class="string">"Filling the <span class="subst">#{container}</span> with <span class="subst">#{liquid}</span>..."</span>
- </code></pre><pre><code><span class="keyword">var</span> fill;
- fill = <span class="function"><span class="keyword">function</span><span class="params">(container, liquid)</span> {</span>
- <span class="keyword">if</span> (liquid == <span class="literal">null</span>) {
- liquid = <span class="string">"coffee"</span>;
- }
- <span class="keyword">return</span> <span class="string">"Filling the "</span> + container + <span class="string">" with "</span> + liquid + <span class="string">"..."</span>;
- };
- </code></pre><script>window.example3 = "fill = (container, liquid = \"coffee\") ->\n \"Filling the #{container} with #{liquid}...\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example3);'>load</div><div class='minibutton ok' onclick='javascript: var fill;
- fill = function(container, liquid) {
- if (liquid == null) {
- liquid = "coffee";
- }
- return "Filling the " + container + " with " + liquid + "...";
- };
- ;alert(fill("cup"));'>run: fill("cup")</div><br class='clear' /></div>
- <p>
- <span id="objects_and_arrays" class="bookmark"></span>
- <b class="header">Objects and Arrays</b>
- The CoffeeScript literals for objects and arrays look very similar to
- their JavaScript cousins. When each property is listed on its own line,
- the commas are optional. Objects may be created using indentation instead
- of explicit braces, similar to <a href="http://yaml.org">YAML</a>.
- </p>
- <div class='code'><pre><code>song = [<span class="string">"do"</span>, <span class="string">"re"</span>, <span class="string">"mi"</span>, <span class="string">"fa"</span>, <span class="string">"so"</span>]
- singers = {<span class="attribute">Jagger</span>: <span class="string">"Rock"</span>, <span class="attribute">Elvis</span>: <span class="string">"Roll"</span>}
- bitlist = [
- <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>
- <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>
- <span class="number">1</span>, <span class="number">1</span>, <span class="number">0</span>
- ]
- kids =
- <span class="attribute">brother</span>:
- <span class="attribute">name</span>: <span class="string">"Max"</span>
- <span class="attribute">age</span>: <span class="number">11</span>
- <span class="attribute">sister</span>:
- <span class="attribute">name</span>: <span class="string">"Ida"</span>
- <span class="attribute">age</span>: <span class="number">9</span>
- </code></pre><pre><code><span class="keyword">var</span> bitlist, kids, singers, song;
- song = [<span class="string">"do"</span>, <span class="string">"re"</span>, <span class="string">"mi"</span>, <span class="string">"fa"</span>, <span class="string">"so"</span>];
- singers = {
- Jagger: <span class="string">"Rock"</span>,
- Elvis: <span class="string">"Roll"</span>
- };
- bitlist = [<span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">0</span>];
- kids = {
- brother: {
- name: <span class="string">"Max"</span>,
- age: <span class="number">11</span>
- },
- sister: {
- name: <span class="string">"Ida"</span>,
- age: <span class="number">9</span>
- }
- };
- </code></pre><script>window.example4 = "song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]\n\nsingers = {Jagger: \"Rock\", Elvis: \"Roll\"}\n\nbitlist = [\n 1, 0, 1\n 0, 0, 1\n 1, 1, 0\n]\n\nkids =\n brother:\n name: \"Max\"\n age: 11\n sister:\n name: \"Ida\"\n age: 9\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example4);'>load</div><div class='minibutton ok' onclick='javascript: var bitlist, kids, singers, song;
- song = ["do", "re", "mi", "fa", "so"];
- singers = {
- Jagger: "Rock",
- Elvis: "Roll"
- };
- bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0];
- kids = {
- brother: {
- name: "Max",
- age: 11
- },
- sister: {
- name: "Ida",
- age: 9
- }
- };
- ;alert(song.join(" ... "));'>run: song.join(" ... ")</div><br class='clear' /></div>
- <p>
- In JavaScript, you can't use reserved words, like <code>class</code>, as properties
- of an object, without quoting them as strings. CoffeeScript notices reserved words
- used as keys in objects and quotes them for you, so you don't have to worry
- about it (say, when using jQuery).
- </p>
- <div class='code'><pre><code>$('.account').attr class: 'active'
- log object.class
- </code></pre><pre><code>$(<span class="string">'.account'</span>).attr({
- <span class="string">"class"</span>: <span class="string">'active'</span>
- });
- log(object[<span class="string">"class"</span>]);
- </code></pre><script>window.example5 = "$('.account').attr class: 'active'\n\nlog object.class\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example5);'>load</div><br class='clear' /></div>
- <p>
- <span id="lexical-scope" class="bookmark"></span>
- <b class="header">Lexical Scoping and Variable Safety</b>
- The CoffeeScript compiler takes care to make sure that all of your variables
- are properly declared within lexical scope — you never need to write
- <code>var</code> yourself.
- </p>
- <div class='code'><pre><code>outer = <span class="number">1</span>
- <span class="function"><span class="title">changeNumbers</span> = -></span>
- inner = -<span class="number">1</span>
- outer = <span class="number">10</span>
- inner = changeNumbers()</code></pre><pre><code><span class="keyword">var</span> changeNumbers, inner, outer;
- outer = <span class="number">1</span>;
- changeNumbers = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> inner;
- inner = -<span class="number">1</span>;
- <span class="keyword">return</span> outer = <span class="number">10</span>;
- };
- inner = changeNumbers();
- </code></pre><script>window.example6 = "outer = 1\nchangeNumbers = ->\n inner = -1\n outer = 10\ninner = changeNumbers()"</script><div class='minibutton load' onclick='javascript: loadConsole(example6);'>load</div><div class='minibutton ok' onclick='javascript: var changeNumbers, inner, outer;
- outer = 1;
- changeNumbers = function() {
- var inner;
- inner = -1;
- return outer = 10;
- };
- inner = changeNumbers();
- ;alert(inner);'>run: inner</div><br class='clear' /></div>
- <p>
- Notice how all of the variable declarations have been pushed up to
- the top of the closest scope, the first time they appear.
- <b>outer</b> is not redeclared within the inner function, because it's
- already in scope; <b>inner</b> 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.
- </p>
- <p>
- This behavior is effectively identical to Ruby's scope for local variables.
- Because you don't have direct access to the <code>var</code> keyword,
- it's impossible to shadow an outer variable on purpose, you may only refer
- to it. So be careful that you're not reusing the name of an external
- variable accidentally, if you're writing a deeply nested function.
- </p>
- <p>
- Although suppressed within this documentation for clarity, all
- CoffeeScript output is wrapped in an anonymous function:
- <code>(function(){ ... })();</code> This safety wrapper, combined with the
- automatic generation of the <code>var</code> keyword, make it exceedingly difficult
- to pollute the global namespace by accident.
- </p>
- <p>
- If you'd like to create top-level variables for other scripts to use,
- attach them as properties on <b>window</b>, or on the <b>exports</b>
- object in CommonJS. The <b>existential operator</b> (covered below), gives you a
- reliable way to figure out where to add them; if you're targeting both
- CommonJS and the browser: <code>exports ? this</code>
- </p>
- <p>
- <span id="conditionals" class="bookmark"></span>
- <b class="header">If, Else, Unless, and Conditional Assignment</b>
- <b>If/else</b> 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. There's also a handy
- postfix form, with the <code>if</code> or <code>unless</code> at the end.
- </p>
- <p>
- CoffeeScript can compile <b>if</b> 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 <b>if</b> statement on a single line.
- </p>
- <div class='code'><pre><code>mood = greatlyImproved <span class="keyword">if</span> singing
- <span class="keyword">if</span> happy <span class="keyword">and</span> knowsIt
- clapsHands()
- chaChaCha()
- <span class="keyword">else</span>
- showIt()
- date = <span class="keyword">if</span> friday <span class="keyword">then</span> sue <span class="keyword">else</span> jill
- </code></pre><pre><code><span class="keyword">var</span> date, mood;
- <span class="keyword">if</span> (singing) {
- mood = greatlyImproved;
- }
- <span class="keyword">if</span> (happy && knowsIt) {
- clapsHands();
- chaChaCha();
- } <span class="keyword">else</span> {
- showIt();
- }
- date = friday ? sue : jill;
- </code></pre><script>window.example7 = "mood = greatlyImproved if singing\n\nif happy and knowsIt\n clapsHands()\n chaChaCha()\nelse\n showIt()\n\ndate = if friday then sue else jill\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example7);'>load</div><br class='clear' /></div>
- <p>
- <span id="splats" class="bookmark"></span>
- <b class="header">Splats...</b>
- The JavaScript <b>arguments object</b> is a useful way to work with
- functions that accept variable numbers of arguments. CoffeeScript provides
- splats <code>...</code>, both for function definition as well as invocation,
- making variable numbers of arguments a little bit more palatable.
- </p>
- <div class='code'><pre><code>gold = silver = rest = <span class="string">"unknown"</span>
- <span class="function"><span class="title">awardMedals</span> = <span class="params">(first, second, others...)</span> -></span>
- gold = first
- silver = second
- rest = others
- contenders = [
- <span class="string">"Michael Phelps"</span>
- <span class="string">"Liu Xiang"</span>
- <span class="string">"Yao Ming"</span>
- <span class="string">"Allyson Felix"</span>
- <span class="string">"Shawn Johnson"</span>
- <span class="string">"Roman Sebrle"</span>
- <span class="string">"Guo Jingjing"</span>
- <span class="string">"Tyson Gay"</span>
- <span class="string">"Asafa Powell"</span>
- <span class="string">"Usain Bolt"</span>
- ]
- awardMedals contenders...
- alert <span class="string">"Gold: "</span> + gold
- alert <span class="string">"Silver: "</span> + silver
- alert <span class="string">"The Field: "</span> + rest
- </code></pre><pre><code><span class="keyword">var</span> awardMedals, contenders, gold, rest, silver,
- slice = [].slice;
- gold = silver = rest = <span class="string">"unknown"</span>;
- awardMedals = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> first, others, second;
- first = <span class="built_in">arguments</span>[<span class="number">0</span>], second = <span class="built_in">arguments</span>[<span class="number">1</span>], others = <span class="number">3</span> <= <span class="built_in">arguments</span>.length ? slice.call(<span class="built_in">arguments</span>, <span class="number">2</span>) : [];
- gold = first;
- silver = second;
- <span class="keyword">return</span> rest = others;
- };
- contenders = [<span class="string">"Michael Phelps"</span>, <span class="string">"Liu Xiang"</span>, <span class="string">"Yao Ming"</span>, <span class="string">"Allyson Felix"</span>, <span class="string">"Shawn Johnson"</span>, <span class="string">"Roman Sebrle"</span>, <span class="string">"Guo Jingjing"</span>, <span class="string">"Tyson Gay"</span>, <span class="string">"Asafa Powell"</span>, <span class="string">"Usain Bolt"</span>];
- awardMedals.apply(<span class="literal">null</span>, contenders);
- alert(<span class="string">"Gold: "</span> + gold);
- alert(<span class="string">"Silver: "</span> + silver);
- alert(<span class="string">"The Field: "</span> + rest);
- </code></pre><script>window.example8 = "gold = silver = rest = \"unknown\"\n\nawardMedals = (first, second, others...) ->\n gold = first\n silver = second\n rest = others\n\ncontenders = [\n \"Michael Phelps\"\n \"Liu Xiang\"\n \"Yao Ming\"\n \"Allyson Felix\"\n \"Shawn Johnson\"\n \"Roman Sebrle\"\n \"Guo Jingjing\"\n \"Tyson Gay\"\n \"Asafa Powell\"\n \"Usain Bolt\"\n]\n\nawardMedals contenders...\n\nalert \"Gold: \" + gold\nalert \"Silver: \" + silver\nalert \"The Field: \" + rest\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example8);'>load</div><div class='minibutton ok' onclick='javascript: var awardMedals, contenders, gold, rest, silver,
- slice = [].slice;
- gold = silver = rest = "unknown";
- awardMedals = function() {
- var first, others, second;
- first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? slice.call(arguments, 2) : [];
- gold = first;
- silver = second;
- return rest = others;
- };
- contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
- awardMedals.apply(null, contenders);
- alert("Gold: " + gold);
- alert("Silver: " + silver);
- alert("The Field: " + rest);
- ;'>run</div><br class='clear' /></div>
- <p>
- <span id="loops" class="bookmark"></span>
- <b class="header">Loops and Comprehensions</b>
- Most of the loops you'll write in CoffeeScript will be <b>comprehensions</b>
- over arrays, objects, and ranges. Comprehensions replace (and compile into)
- <b>for</b> 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.
- </p>
- <div class='code'><pre><code><span class="comment"># Eat lunch.</span>
- eat food <span class="keyword">for</span> food <span class="keyword">in</span> [<span class="string">'toast'</span>, <span class="string">'cheese'</span>, <span class="string">'wine'</span>]
- <span class="comment"># Fine five course dining.</span>
- courses = [<span class="string">'greens'</span>, <span class="string">'caviar'</span>, <span class="string">'truffles'</span>, <span class="string">'roast'</span>, <span class="string">'cake'</span>]
- menu i + <span class="number">1</span>, dish <span class="keyword">for</span> dish, i <span class="keyword">in</span> courses
- <span class="comment"># Health conscious meal.</span>
- foods = [<span class="string">'broccoli'</span>, <span class="string">'spinach'</span>, <span class="string">'chocolate'</span>]
- eat food <span class="keyword">for</span> food <span class="keyword">in</span> foods <span class="keyword">when</span> food <span class="keyword">isnt</span> <span class="string">'chocolate'</span>
- </code></pre><pre><code><span class="keyword">var</span> courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;
- ref = [<span class="string">'toast'</span>, <span class="string">'cheese'</span>, <span class="string">'wine'</span>];
- <span class="keyword">for</span> (j = <span class="number">0</span>, len = ref.length; j < len; j++) {
- food = ref[j];
- eat(food);
- }
- courses = [<span class="string">'greens'</span>, <span class="string">'caviar'</span>, <span class="string">'truffles'</span>, <span class="string">'roast'</span>, <span class="string">'cake'</span>];
- <span class="keyword">for</span> (i = k = <span class="number">0</span>, len1 = courses.length; k < len1; i = ++k) {
- dish = courses[i];
- menu(i + <span class="number">1</span>, dish);
- }
- foods = [<span class="string">'broccoli'</span>, <span class="string">'spinach'</span>, <span class="string">'chocolate'</span>];
- <span class="keyword">for</span> (l = <span class="number">0</span>, len2 = foods.length; l < len2; l++) {
- food = foods[l];
- <span class="keyword">if</span> (food !== <span class="string">'chocolate'</span>) {
- eat(food);
- }
- }
- </code></pre><script>window.example9 = "# Eat lunch.\neat food for food in ['toast', 'cheese', 'wine']\n\n# Fine five course dining.\ncourses = ['greens', 'caviar', 'truffles', 'roast', 'cake']\nmenu i + 1, dish for dish, i in courses\n\n# Health conscious meal.\nfoods = ['broccoli', 'spinach', 'chocolate']\neat food for food in foods when food isnt 'chocolate'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example9);'>load</div><br class='clear' /></div>
- <p>
- Comprehensions should be able to handle most places where you otherwise
- would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>, for example:
- <code>shortNames = (name for name in list when name.length < 5)</code><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.
- </p>
- <div class='code'><pre><code>countdown = (num <span class="keyword">for</span> num <span class="keyword">in</span> [<span class="number">10.</span><span class="number">.1</span>])
- </code></pre><pre><code><span class="keyword">var</span> countdown, num;
- countdown = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> i, results;
- results = [];
- <span class="keyword">for</span> (num = i = <span class="number">10</span>; i >= <span class="number">1</span>; num = --i) {
- results.push(num);
- }
- <span class="keyword">return</span> results;
- })();
- </code></pre><script>window.example10 = "countdown = (num for num in [10..1])\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example10);'>load</div><div class='minibutton ok' onclick='javascript: var countdown, num;
- countdown = (function() {
- var i, results;
- results = [];
- for (num = i = 10; i >= 1; num = --i) {
- results.push(num);
- }
- return results;
- })();
- ;alert(countdown);'>run: countdown</div><br class='clear' /></div>
- <p>
- Note how because we are assigning the value of the comprehensions to a
- variable in the example above, CoffeeScript is collecting the result of
- each iteration into an array. Sometimes functions end with loops that are
- intended to run only for their side-effects. Be careful that you're not
- accidentally returning the results of the comprehension in these cases,
- by adding a meaningful return value — like <code>true</code> — or <code>null</code>,
- to the bottom of your function.
- </p>
- <p>
- To step through a range comprehension in fixed-size chunks,
- use <code>by</code>, for example:<br />
- <code>evens = (x for x in [0..10] by 2)</code>
- </p>
- <p>
- If you don't need the current iteration value you may omit it:<br />
- <code>browser.closeCurrentTab() for [0...count]</code>
- </p>
- <p>
- Comprehensions can also be used to iterate over the keys and values in
- an object. Use <code>of</code> to signal comprehension over the properties of
- an object instead of the values in an array.
- </p>
- <div class='code'><pre><code>yearsOld = <span class="attribute">max</span>: <span class="number">10</span>, <span class="attribute">ida</span>: <span class="number">9</span>, <span class="attribute">tim</span>: <span class="number">11</span>
- ages = <span class="keyword">for</span> child, age <span class="keyword">of</span> yearsOld
- <span class="string">"<span class="subst">#{child}</span> is <span class="subst">#{age}</span>"</span>
- </code></pre><pre><code><span class="keyword">var</span> age, ages, child, yearsOld;
- yearsOld = {
- max: <span class="number">10</span>,
- ida: <span class="number">9</span>,
- tim: <span class="number">11</span>
- };
- ages = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> results;
- results = [];
- <span class="keyword">for</span> (child <span class="keyword">in</span> yearsOld) {
- age = yearsOld[child];
- results.push(child + <span class="string">" is "</span> + age);
- }
- <span class="keyword">return</span> results;
- })();
- </code></pre><script>window.example11 = "yearsOld = max: 10, ida: 9, tim: 11\n\nages = for child, age of yearsOld\n \"#{child} is #{age}\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example11);'>load</div><div class='minibutton ok' onclick='javascript: var age, ages, child, yearsOld;
- yearsOld = {
- max: 10,
- ida: 9,
- tim: 11
- };
- ages = (function() {
- var results;
- results = [];
- for (child in yearsOld) {
- age = yearsOld[child];
- results.push(child + " is " + age);
- }
- return results;
- })();
- ;alert(ages.join(", "));'>run: ages.join(", ")</div><br class='clear' /></div>
- <p>
- If you would like to iterate over just the keys that are defined on the
- object itself, by adding a <code>hasOwnProperty</code>
- check to avoid properties that may be inherited from the prototype, use<br />
- <code>for own key, value of object</code>
- </p>
- <p>
- The only low-level loop that CoffeeScript provides is the <b>while</b> loop. The
- main difference from JavaScript is that the <b>while</b> loop can be used
- as an expression, returning an array containing the result of each iteration
- through the loop.
- </p>
- <div class='code'><pre><code><span class="comment"># Econ 101</span>
- <span class="keyword">if</span> <span class="keyword">this</span>.studyingEconomics
- buy() <span class="keyword">while</span> supply > demand
- sell() <span class="keyword">until</span> supply > demand
- <span class="comment"># Nursery Rhyme</span>
- num = <span class="number">6</span>
- lyrics = <span class="keyword">while</span> num -= <span class="number">1</span>
- <span class="string">"<span class="subst">#{num}</span> little monkeys, jumping on the bed.
- One fell out and bumped his head."</span>
- </code></pre><pre><code><span class="keyword">var</span> lyrics, num;
- <span class="keyword">if</span> (<span class="keyword">this</span>.studyingEconomics) {
- <span class="keyword">while</span> (supply > demand) {
- buy();
- }
- <span class="keyword">while</span> (!(supply > demand)) {
- sell();
- }
- }
- num = <span class="number">6</span>;
- lyrics = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
- <span class="keyword">var</span> results;
- results = [];
- <span class="keyword">while</span> (num -= <span class="number">1</span>) {
- results.push(num + <span class="string">" little monkeys, jumping on the bed. One fell out and bumped his head."</span>);
- }
- <span class="keyword">return</span> results;
- })();
- </code></pre><script>window.example12 = "# Econ 101\nif this.studyingEconomics\n buy() while supply > demand\n sell() until supply > demand\n\n# Nursery Rhyme\nnum = 6\nlyrics = while num -= 1\n \"#{num} little monkeys, jumping on the bed.\n One fell out and bumped his head.\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example12);'>load</div><div class='minibutton ok' onclick='javascript: var lyrics, num;
- if (this.studyingEconomics) {
- while (supply > demand) {
- buy();
- }
- while (!(supply > demand)) {
- sell();
- }
- }
- num = 6;
- lyrics = (function() {
- var results;
- results = [];
- while (num -= 1) {
- results.push(num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
- }
- return results;
- })();
- ;alert(lyrics.join("
- "));'>run: lyrics.join("
- ")</div><br class='clear' /></div>
- <p>
- For readability, the <b>until</b> keyword is equivalent to <code>while not</code>,
- and the <b>loop</b> keyword is equivalent to <code>while true</code>.
- </p>
- <p>
- When using a JavaScript loop to generate functions, it's common to insert
- a closure wrapper in order to ensure that loop variables are closed over,
- and all the generated functions don't just share the final values. CoffeeScript
- provides the <code>do</code> keyword, which immediately invokes a passed function,
- forwarding any arguments.
- </p>
- <div class='code'><pre><code><span class="keyword">for</span> filename <span class="keyword">in</span> list
- <span class="keyword">do</span> <span class="function"><span class="params">(filename)</span> -></span>
- fs.readFile filename, <span class="function"><span class="params">(err, contents)</span> -></span>
- compile filename, contents.toString()</code></pre><pre><code><span class="keyword">var</span> filename, fn, i, len;
- fn = <span class="function"><span class="keyword">function</span><span class="params">(filename)</span> {</span>
- <span class="keyword">return</span> fs.readFile(filename, <span class="function"><span class="keyword">function</span><span class="params">(err, contents)</span> {</span>
- <span class="keyword">return</span> compile(filename, contents.toString());
- });
- };
- <span class="keyword">for</span> (i = <span class="number">0</span>, len = list.length; i < len; i++) {
- filename = list[i];
- fn(filename);
- }
- </code></pre><script>window.example13 = "for filename in list\n do (filename) ->\n fs.readFile filename, (err, contents) ->\n compile filename, contents.toString()"</script><div class='minibutton load' onclick='javascript: loadConsole(example13);'>load</div><br class='clear' /></div>
- <p>
- <span id="slices" class="bookmark"></span>
- <b class="header">Array Slicing and Splicing with Ranges</b>
- Ranges can also be used to extract slices of arrays.
- With two dots (<code>3..6</code>), the range is inclusive (<code>3, 4, 5, 6</code>);
- with three dots (<code>3...6</code>), the range excludes the end (<code>3, 4, 5</code>).
- Slices indices have useful defaults. An omitted first index defaults to
- zero and an omitted second index defaults to the size of the array.
- </p>
- <div class='code'><pre><code>numbers = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>]
- start = numbers[<span class="number">0.</span><span class="number">.2</span>]
- middle = numbers[<span class="number">3.</span>..-<span class="number">2</span>]
- end = numbers[-<span class="number">2.</span>.]
- copy = numbers[..]
- </code></pre><pre><code><span class="keyword">var</span> copy, end, middle, numbers, start;
- numbers = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>];
- start = numbers.slice(<span class="number">0</span…