CoffeeScriptis a little language that compiles into JavaScript. 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.
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern JavaScript syntax (ES6, or ES2015 and later). A CoffeeScript => becomes a JS =>, a CoffeeScript class becomes a JS class and so on. Major new features in CoffeeScript 2 include async functions and JSX. You can read more in the announcement.
This list may be incomplete, and excludes versions of Node that support newer features behind flags; please refer to node.green for full details. You can run the tests in your browser to see what your browser supports. It is your responsibility to ensure that your runtime supports the modern features you use; or that you transpile your code. When in doubt, transpile.
The command-line version of coffee is available as a Node.js utility, requiring Node 6 or later. The core compiler however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see Try CoffeeScript).
The coffee and cake commands will first look in the current folder to see if CoffeeScript is installed locally, and use that version if so. This allows different versions of CoffeeScript to be installed globally and locally.
If you plan to use the --transpile option (see Transpilation) you will need to also install @babel/core either globally or locally, depending on whether you are running a globally or locally installed version of CoffeeScript.
Once installed, you should have access to the coffee command, which can execute scripts, compile .coffee files into .js, and provide an interactive REPL. The coffee command takes the following options:
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run might not support all of that syntax. In that case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, a = obj into a = obj.a. This is done via transpilers like Babel, Bubl or Traceur Compiler. See Build Tools.
To make things easy, CoffeeScript has built-in support for the popular Babel transpiler. You can use it via the --transpile command-line option or the transpile Node API option. To use either, @babel/core must be installed in your project:
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.
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 YAML.
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. ES2015 adopted this feature as their rest parameters.
Comprehensions should be able to handle most places where you otherwise would use a loop, each/forEach, map, or select/filter, for example:
shortNames = (name for name in list when name.length
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.
If you would like to iterate over just the keys that are defined on the object itself, by adding a hasOwnProperty check to avoid properties that may be inherited from the prototype, use for own key, value of object.
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.
Things that would otherwise be statements in JavaScript, when used as part of an expression in CoffeeScript, are converted into expressions by wrapping them in a closure. This lets you do useful things, like assign the result of a comprehension to a variable:
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?.
Just like JavaScript (since ES2015), CoffeeScript has destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment:
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.
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.
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.
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.
Note that the CoffeeScript compiler does not resolve modules; writing an import or export statement in CoffeeScript will produce an import or export statement in the resulting output. Such statements can be run by all modern browsers (when the script is referenced via ) and by Node.js when the output .js files are in a folder where the nearest parent package.json file contains "type": "module". Because the runtime is evaluating the generated output, the import statements must reference the output files; so if file.coffee is output as file.js, it needs to be referenced as file.js in the import statement, with the .js extension included.
Also, any file with an import or export statement will be output without a top-level function safety wrapper; in other words, importing or exporting modules will automatically trigger bare mode for that file. This is because per the ES2015 spec, import or export statements must occur at the topmost scope.
CoffeeScript supports interspersed XML elements, without the need for separate plugins or special settings. The XML elements will be compiled as such, outputting JSX that could be parsed like any normal JSX file, for example by Babel with the React JSX transform. CoffeeScript does not output React.createElement calls or any code specific to React or any other framework. It is up to you to attach another step in your build chain to convert this JSX to whatever function calls you wish the XML elements to compile to.
--bare and --no-header are important because Flow requires the first line of the file to be the comment // @flow. If you configure your build chain to compile CoffeeScript and pass the result to Flow in-memory, you can get better performance than this example; and a proper build tool should be able to watch your CoffeeScript files and recompile and type-check them for you on save.
CoffeeScript includes support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.
When CoffeeScript was designed, var was intentionally omitted. 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.
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, and the second is a function expression. As stated above, in CoffeeScript everything is an expression, 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.
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 that is slightly more verbose but just as effective:
3a8082e126