
* Docs: named functions and function declarations * No more prototypal `extends`; update docs and example * More comprehensive documentation of the existential operator; closes #1631 * Better document operators, including `from` * No fat arrow class methods anymore * Destructuring shouldn’t say that default values are applied in case of undefined or null * Spinoff generator and async functions into their own sections; reorder things so that the sections on functions come just before classes, and destructuring goes next to the operators (which discuss assignment) * Rewrite “CoffeeScript 2” section, making it less practical and more explanatory; move practical info into “Usage” * Update “Variable Scoping and Lexical Safety” section to remove incorrect reference to Ruby (fixes #2360), add missing details about the safety wrapper, add note about `let`/`const`. * Updated browser compiler * Updated docs * Rewrite Literate CoffeeScript breaking changes * Split apart the “Breaking Changes” and “Unsupported Features” sections into separate sidebar items and files * Add example of `not in`, closes #3281 * Fix words in bold that should be in backticks * Consolidate some breaking changes sections * Add Node API documentation; closes #3551 * Move the chaining documentation out of the changelog into its own section
2.8 KiB
Loops and Comprehensions
Most of the loops you’ll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for
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.
codeFor('array_comprehensions')
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 < 5)
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.
codeFor('range_comprehensions', 'countdown')
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 true
— or null
, to the bottom of your function.
To step through a range comprehension in fixed-size chunks, use by
, for example:
evens = (x for x in [0..10] by 2)
If you don’t need the current iteration value you may omit it:
browser.closeCurrentTab() for [0...count]
Comprehensions can also be used to iterate over the keys and values in an object. Use of
to signal comprehension over the properties of an object instead of the values in an array.
codeFor('object_comprehensions', 'ages.join(", ")')
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
.
To iterate a generator function, use from
. See Generator Functions.
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.
codeFor('while', 'lyrics.join("\\n")')
For readability, the until
keyword is equivalent to while not
, and the loop
keyword is equivalent to while true
.
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 do
keyword, which immediately invokes a passed function, forwarding any arguments.
codeFor('do')