CoffeeScript 是一种编译成 JavaScript 的小语言。 在那笨拙的 Java 风格的外表下,JavaScript 一直拥有一颗美丽的心。CoffeeScript 试图以一种简单的方式展现 JavaScript 的优点。

CoffeeScript 的黄金法则:“它只是 JavaScript。” 代码会一对一地编译成等效的 JS,并且在运行时没有解释。您可以从 CoffeeScript(反之亦然)无缝地使用任何现有的 JavaScript 库。编译后的输出是可读的、格式良好的,并且往往运行速度与等效的手写 JavaScript 一样快或更快。

最新版本: 2.7.0

# Install locally for a project:
npm install --save-dev coffeescript

# Install globally to execute .coffee files anywhere:
npm install --global coffeescript

概述

CoffeeScript 在 顶部左侧,编译后的 JavaScript 输出在 底部右侧。CoffeeScript 是可编辑的!

CoffeeScript 2

CoffeeScript 2 的新特性?

CoffeeScript 2 中最大的变化是,现在 CoffeeScript 编译器会生成现代 JavaScript 语法(ES6 或 ES2015 及更高版本)。CoffeeScript 的 => 会变成 JS 的 =>,CoffeeScript 的 class 会变成 JS 的 class,等等。CoffeeScript 2 中的主要新特性包括 异步函数JSX。您可以在 公告 中了解更多信息。

从 CoffeeScript 1.x 到 2 只有很少的 重大变更;我们希望大多数项目的升级过程都很顺利。

兼容性

CoffeeScript 支持的大多数现代 JavaScript 特性可以在 Node 7.6+ 中原生运行,这意味着 Node 可以运行 CoffeeScript 的输出,而无需任何进一步的处理。以下是一些值得注意的例外情况

此列表可能不完整,并且不包括在标志后面支持更新特性的 Node 版本;有关完整详细信息,请参阅 node.green。您可以在 浏览器中运行测试 以查看您的浏览器支持哪些功能。您有责任确保您的运行时支持您使用的现代特性;或者您需要 转译 您的代码。如有疑问,请转译。

有关与其他 JavaScript 框架和工具的兼容性,请参阅 集成

安装

coffee 的命令行版本作为 Node.js 实用程序提供,需要 Node 6 或更高版本。但是,核心编译器 不依赖于 Node,可以在任何 JavaScript 环境或浏览器中运行(请参阅 尝试 CoffeeScript)。

要安装,首先确保您拥有 Node.js 最新稳定版本的有效副本。然后,您可以使用 npm 全局安装 CoffeeScript

npm install --global coffeescript

这将使 coffeecake 命令在全局范围内可用。

如果您在项目中使用 CoffeeScript,您应该为该项目本地安装它,以便 CoffeeScript 的版本被跟踪为您的项目依赖项之一。在该项目的文件夹中

npm install --save-dev coffeescript

coffeecake 命令将首先在当前文件夹中查找是否本地安装了 CoffeeScript,如果已安装,则使用该版本。这允许在全局和本地安装不同版本的 CoffeeScript。

如果您打算使用 --transpile 选项(请参阅 转译),您还需要全局或本地安装 @babel/core,具体取决于您运行的是全局安装的 CoffeeScript 版本还是本地安装的版本。

使用

命令行

安装完成后,您应该可以使用 coffee 命令,该命令可以执行脚本、将 .coffee 文件编译成 .js,并提供交互式 REPL。coffee 命令接受以下选项

选项 描述
-c, --compile .coffee 脚本编译成同名 .js JavaScript 文件。
-t, --transpile 在保存或运行生成的 JavaScript 之前,将 CoffeeScript 编译器的输出通过 Babel。需要安装 @babel/core,以及在要编译的文件或文件夹的路径中,在 .babelrc 文件或具有 babel 键的 package.json 中传递给 Babel 的选项。请参阅 转译
-m, --map 与编译后的 JavaScript 文件一起生成源代码映射。还会向 JavaScript 添加 sourceMappingURL 指令。
-M, --inline-map 就像--map一样,但是将源映射直接包含在编译后的 JavaScript 文件中,而不是单独的文件中。
-i, --interactive 启动一个交互式的 CoffeeScript 会话,用于尝试简短的代码片段。与不带参数调用coffee相同。
-o, --output [DIR] 将所有编译后的 JavaScript 文件写入指定的目录。与--compile--watch结合使用。
-w, --watch 监视文件更改,并在任何文件更新时重新运行指定的命令。
-p, --print 不将 JavaScript 作为文件写入,而是直接打印到stdout
-s, --stdio 将 CoffeeScript 传输到 STDIN,并通过 STDOUT 获取 JavaScript。适合与用其他语言编写的进程一起使用。例如
cat src/cake.coffee | coffee -sc
-l, --literate 将代码解析为 Literate CoffeeScript。只有在直接通过stdio传递代码或使用某种无扩展名文件名时才需要指定此选项。
-e, --eval 直接从命令行编译并打印一小段 CoffeeScript 代码。例如
coffee -e "console.log num for num in [10..1]"
-r, --require [MODULE] 在启动 REPL 或使用--eval标志评估给定的代码之前,require()给定的模块。
-b, --bare 编译 JavaScript,不使用顶层函数安全包装器
--no-header 抑制“由 CoffeeScript 生成”的标题。
--nodejs node可执行文件有一些有用的选项可以设置,例如--debug--debug-brk--max-stack-size--expose-gc。使用此标志将选项直接转发到 Node.js。要传递多个标志,请多次使用--nodejs
--ast 生成 CoffeeScript 的节点的抽象语法树。用于与 JavaScript 构建工具集成。
--tokens 不解析 CoffeeScript,只进行词法分析,并打印出标记流。用于调试编译器。
-n, --nodes 不编译 CoffeeScript,只进行词法分析和解析,并打印出解析树。用于调试编译器。

示例

  • src.coffee文件的目录树编译成lib.js文件的并行树
    coffee --compile --output lib/ src/
  • 监视文件更改,并在每次保存文件时重新编译
    coffee --watch --compile experimental.coffee
  • 将文件列表连接成单个脚本
    coffee --join project.js --compile src/*.coffee
  • 打印出从单行代码中编译的 JS
    coffee -bpe "alert i for i in [0..10]"
  • 现在一起,在您处理项目时监视和重新编译整个项目
    coffee -o lib/ -cw src/
  • 启动 CoffeeScript REPL(Ctrl-D退出,Ctrl-V用于多行)
    coffee

要使用--transpile,请参阅转译

Node.js

如果您想使用 Node.js 的 CommonJS 来require CoffeeScript 文件,例如require './app.coffee',您必须首先将 CoffeeScript 注册为扩展

require 'coffeescript/register'

App = require './app' # The .coffee extension is optional

如果您想使用编译器的 API,例如创建一个应用程序,该应用程序可以动态编译 CoffeeScript 字符串,您可以require整个模块

CoffeeScript = require 'coffeescript'

eval CoffeeScript.compile 'console.log "Mmmmm, I could really go for some #{Math.pi}"'

compile方法的签名为compile(code, options),其中code是 CoffeeScript 代码字符串,可选的options是一个对象,包含以下属性中的部分或全部

  • options.sourceMap,布尔值:如果为 true,将生成源映射;并且compile将返回一个对象,而不是返回一个字符串,该对象的格式为{js, v3SourceMap, sourceMap}
  • options.inlineMap,布尔值:如果为 true,将源映射作为 base64 编码的字符串输出到底部注释中。
  • options.filename,字符串:用于源映射的文件名。它可以包含路径(相对或绝对)。
  • options.bare,布尔值:如果为 true,则不使用顶层函数安全包装器输出。
  • options.header,布尔值:如果为 true,则输出Generated by CoffeeScript标题。
  • options.transpile对象:如果设置,则必须是一个对象,其中包含传递给 Babel 的选项。请参阅转译
  • options.ast,布尔值:如果为 true,则返回输入 CoffeeScript 源代码的抽象语法树。

转译

CoffeeScript 2 生成使用最新现代语法的 JavaScript。您希望代码运行的运行时或浏览器可能不支持所有这些语法。在这种情况下,我们希望将现代 JavaScript 转换为可以在旧版本的 Node 或旧浏览器中运行的旧 JavaScript;例如,将{ a } = obj转换为a = obj.a。这是通过像BabelBubléTraceur Compiler这样的转译器完成的。请参阅构建工具

快速入门

从项目的根目录

npm install --save-dev @babel/core @babel/preset-env
echo '{ "presets": ["@babel/env"] }' > .babelrc
coffee --compile --transpile --inline-map some-file.coffee

使用 CoffeeScript 编译器进行转译

为了方便起见,CoffeeScript 内置支持流行的Babel转译器。您可以通过--transpile命令行选项或transpile Node API 选项使用它。要使用任一选项,必须在您的项目中安装@babel/core

npm install --save-dev @babel/core

或者,如果您在项目文件夹之外运行coffee命令,使用全局安装的coffeescript模块,则需要全局安装@babel/core

npm install --global @babel/core

默认情况下,Babel 不会执行任何操作——它不会对您想要转译的内容做出假设。您需要为它提供一个配置,以便它知道该怎么做。一种方法是在包含您要编译的文件的文件夹中或在这些文件路径之上的任何父文件夹中创建一个.babelrc文件。(Babel 也支持其他方法。)一个最小的.babelrc文件只是{ "presets": ["@babel/env"] }。这意味着您已经安装了@babel/preset-env

npm install --save-dev @babel/preset-env  # Or --global for non-project-based usage

请参阅Babel 的网站以了解预设和插件以及您拥有的众多选项。您可能需要的另一个预设是@babel/plugin-transform-react-jsx,如果您使用的是 React 的 JSX(JSX 也可以与其他框架一起使用)。

一旦您安装了@babel/core@babel/preset-env(或其他预设或插件),并且.babelrc文件(或其他等效文件)就位,您可以使用coffee --transpile通过 Babel 传输 CoffeeScript 的输出,使用您保存的选项。

如果您通过Node API使用 CoffeeScript,您在其中使用要编译的字符串和options对象调用CoffeeScript.compile,则options对象的transpile键应该是 Babel 选项

CoffeeScript.compile(code, {transpile: {presets: ['@babel/env']}})

您也可以在不使用transpile选项的情况下转译 CoffeeScript 的输出,例如作为构建链的一部分。这使您可以使用除 Babel 之外的其他转译器,并让您更好地控制流程。有许多很棒的任务运行器用于设置 JavaScript 构建链,例如GulpWebpackGruntBroccoli

垫片

请注意,转译不会自动为您的代码提供垫片。CoffeeScript 本身将输出Array.indexOf,如果您使用in运算符,或者解构或展开/剩余语法;以及Function.bind,如果您在类中使用绑定(=>)方法。两者都支持 Internet Explorer 9+ 和所有更新的浏览器,但如果您需要支持 Internet Explorer 8 或更低版本,并且正在使用会导致这些方法输出的功能,则需要提供垫片。如果您自己的代码使用这些方法或最近版本的 JavaScript 中添加的其他方法,您也需要提供垫片。一个垫片选项是@babel/polyfill,尽管有许多其他策略

语言参考

本参考的结构使其可以从上到下阅读,如果您愿意。后面的部分使用之前介绍的概念和语法。假设您熟悉 JavaScript。在以下所有示例中,左侧提供源 CoffeeScript,右侧提供直接编译成 JavaScript 的代码。

许多示例可以通过按下右侧的 按钮来运行(在有意义的情况下)。左侧的 CoffeeScript 是可编辑的,JavaScript 会随着您的编辑而更新。

首先,基础知识:CoffeeScript 使用显著的空格来分隔代码块。您不需要使用分号;来终止表达式,结束行就足够了(尽管分号仍然可以用来将多个表达式放在一行上)。不使用大括号{ }来包围函数if 语句switchtry/catch中的代码块,而是使用缩进。

如果您传递参数,则不需要使用括号来调用函数。隐式调用会向前包裹到行或块表达式的末尾。
console.log sys.inspect objectconsole.log(sys.inspect(object));

函数

函数由可选的参数列表(括号内)、箭头和函数体定义。空函数看起来像这样:->

函数也可以为参数设置默认值,如果传入的参数缺失(undefined),则将使用这些默认值。

字符串

与 JavaScript 和许多其他语言一样,CoffeeScript 支持由"'字符分隔的字符串。CoffeeScript 还支持"引号字符串中的字符串插值,使用#{ … }。单引号字符串是文字字符串。您甚至可以在对象键中使用插值。

CoffeeScript 允许使用多行字符串。除非以反斜杠结尾,否则行之间用单个空格连接。缩进被忽略。

块字符串,由 """''' 定界,可用于保存格式化或缩进敏感的文本(或者,如果您不想转义引号和撇号)。开始块的缩进级别在整个块中保持一致,因此您可以将所有内容与代码主体对齐。

双引号块字符串,与其他双引号字符串一样,允许插值。

对象和数组

CoffeeScript 中的对象和数组字面量看起来与它们的 JavaScript 对应物非常相似。当每个属性都列在单独的行上时,逗号是可选的。对象可以使用缩进而不是显式大括号创建,类似于 YAML

当您希望使用相同名称的变量设置键时,CoffeeScript 有一个创建对象的快捷方式。请注意,此简写需要 {}

注释

在 CoffeeScript 中,注释由 # 字符到行尾,或从 ### 到下一个 ### 出现的位置表示。注释被编译器忽略,尽管编译器尽力在编译后将您的注释重新插入输出 JavaScript 中。

内联 ### 注释使 类型注释 成为可能。

词法作用域和变量安全性

CoffeeScript 编译器会确保所有变量都在词法作用域内正确声明——您永远不需要自己编写 var

注意所有变量声明是如何被推到最接近的作用域的顶部的,即它们第一次出现的地方。outer 在内部函数中没有重新声明,因为它已经在作用域内;另一方面,函数内的 inner 不应该能够改变同名外部变量的值,因此它有自己的声明。

由于您无法直接访问 var 关键字,因此不可能故意遮蔽外部变量,您只能引用它。因此,如果您正在编写一个深度嵌套的函数,请注意您是否不小心重用了外部变量的名称。

虽然为了清晰起见,在本文档中被抑制,但所有 CoffeeScript 输出(除了包含 importexport 语句的文件)都包装在一个匿名函数中:(function(){ … })();。这种安全包装器,加上自动生成 var 关键字,使得意外污染全局命名空间变得极其困难。(安全包装器可以使用 bare 选项 禁用,并且在使用模块时是不必要的,并且会自动禁用。)

如果您想创建供其他脚本使用的顶级变量,请将它们作为属性附加到 window 上;将它们作为属性附加到 CommonJS 中的 exports 对象上;或者使用 export 语句。如果您同时针对 CommonJS 和浏览器,则 存在运算符(下面介绍)为您提供了一种可靠的方法来确定将它们添加到哪里:exports ? this

由于 CoffeeScript 负责所有变量声明,因此无法使用 ES2015 的 letconst 声明变量。 这是故意的;我们认为,不必考虑变量声明而获得的简洁性胜过拥有三种不同方式声明变量的好处。

如果、否则、除非和条件赋值

if/else 语句可以在不使用括号和大括号的情况下编写。与函数和其他块表达式一样,多行条件语句由缩进分隔。还有一种方便的后缀形式,ifunless 在末尾。

CoffeeScript 可以将 if 语句编译成 JavaScript 表达式,在可能的情况下使用三元运算符,否则使用闭包包装。CoffeeScript 中没有显式的三元语句——您只需在单行上使用常规的 if 语句。

散点,或剩余参数/扩展语法

JavaScript arguments 对象是处理接受可变数量参数的函数的一种有用方法。CoffeeScript 提供了散点 ...,用于函数定义和调用,使可变数量的参数更易于处理。ES2015 将此功能作为他们的 剩余参数 采用。

散点还允许我们省略数组元素…

…以及对象属性。

在 ECMAScript 中,这被称为 扩展语法,并且从 ES2015 开始支持数组,从 ES2018 开始支持对象。

循环和推导

您在 CoffeeScript 中编写的多数循环将是针对数组、对象和范围的 **推导**。推导替换(并编译成)for 循环,并带有可选的保护子句和当前数组索引的值。与 for 循环不同,数组推导是表达式,可以返回和赋值。

推导应该能够处理大多数您原本会使用循环、each/forEachmapselect/filter 的地方,例如
shortNames = (name for name in list when name.length < 5)
如果您知道循环的开始和结束,或者想要以固定大小的增量逐步执行,可以使用范围来指定理解的开始和结束。

请注意,因为我们在上面的示例中将理解的值分配给一个变量,所以 CoffeeScript 将每次迭代的结果收集到一个数组中。有时函数以仅为其副作用而运行的循环结束。请小心,不要在这些情况下意外返回理解的结果,方法是在函数底部添加有意义的返回值(如 true)或 null

要以固定大小的块逐步执行范围理解,请使用 by,例如:evens = (x for x in [0..10] by 2)

如果您不需要当前迭代值,可以省略它:browser.closeCurrentTab() for [0...count]

理解也可以用于迭代对象中的键和值。使用 of 来表示对对象的属性而不是数组中的值的理解。

如果您想仅迭代对象本身定义的键,可以通过添加 hasOwnProperty 检查来避免可能从原型继承的属性,使用 for own key, value of object

要迭代生成器函数,请使用 from。请参见 生成器函数

CoffeeScript 提供的唯一低级循环是 while 循环。与 JavaScript 的主要区别在于 while 循环可以用作表达式,返回包含循环每次迭代结果的数组。

为了可读性,until 关键字等效于 while notloop 关键字等效于 while true

当使用 JavaScript 循环生成函数时,通常会插入闭包包装器,以确保闭包循环变量,并且所有生成的函数不会仅仅共享最终值。CoffeeScript 提供了 do 关键字,它会立即调用传递的函数,并转发任何参数。

使用范围进行数组切片和拼接

范围也可以用于提取数组的切片。使用两个点 (3..6),范围是包含的 (3, 4, 5, 6);使用三个点 (3...6),范围不包括结束 (3, 4, 5)。切片索引具有有用的默认值。省略的第一个索引默认为零,省略的第二个索引默认为数组的大小。

相同的语法可以与赋值一起使用,用新值替换数组的一部分,将其拼接。

请注意,JavaScript 字符串是不可变的,不能拼接。

一切都是表达式(至少,尽可能地)

您可能已经注意到,即使我们没有在 CoffeeScript 函数中添加 return 语句,它们仍然会返回其最终值。CoffeeScript 编译器试图确保语言中的所有语句都可以用作表达式。观察下面的函数中 return 如何被推送到每个可能的执行分支中。

即使函数始终会返回其最终值,但当您知道已完成时,在函数体中编写显式返回 (return value) 也是可能的,并且鼓励这样做。

因为变量声明发生在作用域的顶部,所以即使对于以前从未见过的变量,赋值也可以在表达式中使用

在 CoffeeScript 中,原本在 JavaScript 中是语句的东西,当用作表达式的一部分时,会通过将其包装在闭包中来转换为表达式。这使您可以做一些有用的事情,例如将理解的结果分配给一个变量

以及一些愚蠢的事情,例如将 try/catch 语句直接传递给函数调用

JavaScript 中有一些语句无法有意义地转换为表达式,即 breakcontinuereturn。如果您在代码块中使用它们,CoffeeScript 不会尝试执行转换。

运算符和别名

因为 == 运算符经常会导致不希望的强制转换,是不及物的,并且与其他语言中的含义不同,所以 CoffeeScript 将 == 编译为 ===,将 != 编译为 !==。此外,is 编译为 ===isnt 编译为 !==

您可以使用 not 作为 ! 的别名。

对于逻辑,and 编译为 &&or 编译为 ||

可以使用 then 来分隔条件和表达式,而不是换行符或分号,在 whileif/elseswitch/when 语句中。

YAML 中一样,onyes 与布尔值 true 相同,而 offno 与布尔值 false 相同。

unless 可以用作 if 的反义词。

作为 this.property 的快捷方式,您可以使用 @property

您可以使用 in 来测试数组是否存在,使用 of 来测试 JavaScript 对象键是否存在。

for 循环中,from 编译为 ES2015 of。(是的,这很不幸;CoffeeScript of 早于 ES2015 of。)

为了简化数学表达式,** 可以用于求幂,// 执行地板除法。% 的工作方式与 JavaScript 中相同,而 %% 提供 “被除数相关的模运算”

现在一起

CoffeeScript JavaScript
is ===
isnt !==
not !
and &&
or ||
true, yes, on true
false, no, off false
@, this this
a in b [].indexOf.call(b, a) >= 0
a of b a in b
for a from b for (a of b)
a ** b a ** b
a // b Math.floor(a / b)
a %% b (a % b + b) % b

存在运算符

在 JavaScript 中检查变量是否存在有点困难。if (variable) … 接近,但对于零、空字符串和 false(仅举最常见的例子)失败。CoffeeScript 的存在运算符 ? 返回 true,除非变量为 nullundefined 或未声明,这使其类似于 Ruby 的 nil?

它也可以用于比 JavaScript 模式 a = a || value 提供的更安全的条件赋值,适用于可能处理数字或字符串的情况。

请注意,如果编译器知道 a 在作用域内并且已声明,则 a? 编译为 a != null,而不是 a !== null!=null 进行松散比较,它也同时与 undefined 进行比较。反之亦然,对于 not a?unless a? 也是如此。

如果一个变量可能未声明,编译器会进行彻底检查。这就是 JavaScript 程序员在想要检查一个神秘变量是否存在时应该输入的内容。

存在运算符 ?. 的访问器变体可用于吸收属性链中的空引用。在基值可能为 nullundefined 的情况下,使用它代替点访问器 .。如果所有属性都存在,则您将获得预期结果,如果链断开,则返回 undefined 而不是会引发的 TypeError

为了完整性

示例 定义
a? 测试 a 是否在作用域内且 a != null
a ? b 如果 a 在作用域内且 a != null,则返回 a;否则,返回 b
a?.ba?['b'] 如果 a 在作用域内且 a != null,则返回 a.b;否则,返回 undefined
a?(b, c)a? b, c 如果 a 在作用域内且可调用,则返回调用 a(带参数 bc)的结果;否则,返回 undefined
a ?= b 如果 a 不在作用域内或 a == null,则将 b 的值分配给 a;生成 a 的新值

链接函数调用

前导 . 会关闭所有打开的调用,从而允许更简单的链接语法。

解构赋值

就像 JavaScript(从 ES2015 开始)一样,CoffeeScript 也有解构赋值语法。当您将数组或对象字面量分配给一个值时,CoffeeScript 会将两边拆开并相互匹配,将右侧的值分配给左侧的变量。在最简单的情况下,它可以用于并行赋值

但它对于处理返回多个值的函数也很有用。

解构赋值可以与任何深度的数组和对象嵌套一起使用,以帮助提取深度嵌套的属性。

解构赋值甚至可以与 splat 结合使用。

展开可以用于从数组末尾检索元素,而无需分配其剩余的值。它也适用于函数参数列表。

解构赋值在与类构造函数结合使用时也很有用,可以将属性从传递给构造函数的选项对象分配给您的实例。

上面的示例还演示了,如果解构的对象或数组中缺少属性,您可以像在 JavaScript 中一样提供默认值。但请注意,与存在运算符不同,默认值仅在值缺失或为 undefined 时应用——传递 null 将设置 null 的值,而不是默认值。

绑定(胖箭头)函数

在 JavaScript 中,this 关键字是动态作用域的,表示当前函数所附加到的对象。如果您将函数作为回调传递或将其附加到不同的对象,则 this 的原始值将丢失。如果您不熟悉此行为,这篇 Digital Web 文章 对这些怪癖进行了很好的概述。

胖箭头 => 可用于定义函数,并将其绑定到 this 的当前值,就在现场。这在使用基于回调的库(如 Prototype 或 jQuery)时很有用,用于创建要传递给 each 的迭代器函数,或用于与 on 一起使用的事件处理程序函数。使用胖箭头创建的函数能够访问定义它们的 this 的属性。

如果我们在上面的回调中使用 ->,则 @customer 将引用 DOM 元素的未定义“customer”属性,尝试在其上调用 purchase() 将引发异常。

胖箭头是 CoffeeScript 最受欢迎的功能之一,ES2015 采用了它;因此 CoffeeScript 2 将 => 编译为 ES =>

生成器函数

CoffeeScript 通过 yield 关键字支持 ES2015 生成器函数。没有 function*(){} 这种无稽之谈——CoffeeScript 中的生成器只是一个会产生值的函数。

yield* 被称为 yield fromyield return 可以用于强制不产生值的生成器。

您可以使用 for…from 迭代生成器函数。

异步函数

ES2017 的 异步函数 通过 await 关键字支持。与生成器一样,不需要 async 关键字;CoffeeScript 中的异步函数只是一个会等待的函数。

类似于 yield return 如何强制生成器,await return 可以用于强制函数为异步函数。

CoffeeScript 1 提供了 `class` 和 `extends` 关键字作为语法糖,用于处理原型函数。随着 ES2015 的发布,JavaScript 也采用了这些关键字;因此,CoffeeScript 2 将其 `class` 和 `extends` 关键字编译为 ES2015 类。

可以使用方法名前的 `@` 定义静态方法

最后,类定义是可执行代码块,这为有趣的元编程可能性提供了可能。在类定义的上下文中,`this` 是类对象本身;因此,您可以使用 `@property: value` 赋值静态属性。

原型继承

除了支持 ES2015 类之外,CoffeeScript 还提供了一种用于处理原型的快捷方式。`::` 运算符可以快速访问对象的原型

Switch/When/Else

JavaScript 中的 `switch` 语句有点笨拙。您需要记住在每个 `case` 语句的末尾添加 `break`,以避免意外地落入默认情况。CoffeeScript 可以防止意外落入,并将 `switch` 转换为可返回、可赋值的表达式。格式为:`switch` 条件、`when` 子句、`else` 默认情况。

与 Ruby 一样,CoffeeScript 中的 `switch` 语句可以为每个 `when` 子句取多个值。如果任何值匹配,则该子句运行。

`switch` 语句也可以在没有控制表达式的情况下使用,将其转换为 `if`/`else` 链的更简洁的替代方案。

Try/Catch/Finally

`try` 表达式与 JavaScript 中的 `try` 语句具有相同的语义,尽管在 CoffeeScript 中,您可以省略 `catch` 和 `finally` 部分。如果不需要错误参数,`catch` 部分也可以省略它。

链式比较

CoffeeScript 从 Python 中借鉴了 链式比较 - 使测试值是否在某个范围内变得容易。

块正则表达式

与块字符串和注释类似,CoffeeScript 支持块正则表达式 - 扩展的正则表达式,忽略内部空格,可以包含注释和插值。以 Perl 的 `x` 修饰符为模型,CoffeeScript 的块正则表达式由 `///` 分隔,对于使复杂的正则表达式可读性强有很大帮助。引用 CoffeeScript 源代码

标记模板字面量

CoffeeScript 支持 ES2015 标记模板字面量,它允许自定义字符串插值。如果您立即在字符串前加上函数名(两者之间没有空格),CoffeeScript 将输出此“函数加字符串”组合作为 ES2015 标记模板字面量,它将 按预期行为:调用该函数,参数是构成插值字符串的输入文本和表达式部分。然后,该函数可以将这些部分组装成输出字符串,提供自定义字符串插值。

模块

ES2015 模块 在 CoffeeScript 中得到支持,具有非常相似的 `import` 和 `export` 语法

动态导入 也得到支持,并带有强制性的括号

请注意,CoffeeScript 编译器**不会解析模块**;在 CoffeeScript 中编写 `import` 或 `export` 语句将在生成的输出中生成 `import` 或 `export` 语句。这些语句可以在所有现代浏览器中运行(当脚本通过 `<script type="module">` 引用时)以及 通过 Node.js 运行,当输出的 `.js` 文件位于最近的父 `package.json` 文件包含 `“type”: “module”` 的文件夹中时。由于运行时正在评估生成的输出,因此 `import` 语句必须引用输出文件;因此,如果 `file.coffee` 输出为 `file.js`,则需要在 `import` 语句中将其引用为 `file.js`,包括 `.js` 扩展名。

此外,任何包含 `import` 或 `export` 语句的文件都将输出,没有 顶级函数安全包装器;换句话说,导入或导出模块将自动为该文件触发 模式。这是因为根据 ES2015 规范,`import` 或 `export` 语句必须出现在最顶层的范围内。

嵌入式 JavaScript

希望您永远不需要使用它,但如果您需要在 CoffeeScript 中插入 JavaScript 代码片段,可以使用反引号将其直接传递。

使用反斜杠转义反引号:` \`​` 变成 ` `​`。

在反引号之前使用更多反斜杠转义反斜杠:` \\\`​` 变成 ` \`​`。

您也可以使用三个反引号嵌入 JavaScript 代码块。如果您需要在 JavaScript 代码块中使用反引号,这比转义反引号更容易。

JSX

JSX 是包含嵌入式 XML 元素的 JavaScript。虽然它是为 React 设计的,但它并不特定于任何特定的库或框架。

CoffeeScript 支持嵌入式 XML 元素,无需单独的插件或特殊设置。XML 元素将被编译为 JSX,输出可以像任何正常的 JSX 文件一样被解析,例如通过 带有 React JSX 变换的 Babel。CoffeeScript 不会输出 React.createElement 调用或任何特定于 React 或任何其他框架的代码。由您决定在构建链中添加另一个步骤,将此 JSX 转换为您希望 XML 元素编译到的任何函数调用。

就像在 JSX 和 HTML 中一样,使用 <> 表示 XML 标签。您可以使用 {} 在标签内插入 CoffeeScript 代码。为了避免编译错误,当使用 <> 表示“小于”或“大于”时,您应该将运算符括在空格中,以将其与 XML 标签区分开来。所以 i < len,而不是 i<len。编译器尝试在它能确定您的意图时宽容,但始终在“小于”和“大于”运算符周围放置空格将消除歧义。

较旧的插件或 CoffeeScript 的分支支持 JSX 语法,并将其称为 CSX 或 CJSX。它们也经常使用 .cjsx 文件扩展名,但这不再必要;普通的 .coffee 就可以了。

类型注释

可以使用 Flow注释类型语法 在 CoffeeScript 中实现静态类型检查。

CoffeeScript 本身不进行任何类型检查;您在上面看到的 JavaScript 输出需要传递给 Flow 才能验证您的代码。我们预计大多数人会为此使用 构建工具,但以下是如何使用 CoffeeScriptFlow 命令行工具以最简单的方式执行此操作,假设您已在项目文件夹中 安装了 Flow最新的 CoffeeScript

coffee --bare --no-header --compile app.coffee && npm run flow

--bare--no-header 很重要,因为 Flow 要求文件的第一行为注释 // @flow。如果您将构建链配置为编译 CoffeeScript 并将结果传递给内存中的 Flow,则可以获得比此示例更好的性能;一个合适的构建工具应该能够监视您的 CoffeeScript 文件,并在保存时重新编译和类型检查它们。

如果您知道使用 CoffeeScript 实现静态类型检查的另一种方法,请 创建一个问题 并告诉我们。

文学 CoffeeScript

除了用作普通的编程语言外,CoffeeScript 也可以用“文学”模式编写。如果您将文件命名为 .litcoffee 扩展名,则可以将其编写为 Markdown 文档——一个也恰好是可执行 CoffeeScript 代码的文档。编译器将把任何缩进块(Markdown 表示源代码的方式)视为可执行代码,并将其余部分视为注释。代码块还必须与注释之间至少有一行空行隔开。

仅仅为了好玩,编译器的一部分目前以这种方式实现:请查看 作为文档原始 以及 在文本编辑器中正确突出显示

一些注意事项

  • 代码块需要保持彼此之间一致的缩进。当编译器解析您的文学 CoffeeScript 文件时,它首先丢弃所有非代码块行,然后将剩余部分解析为普通的 CoffeeScript 文件。因此,代码块需要像注释行不存在一样编写,并保持一致的缩进(包括它们是使用制表符还是空格缩进)。
  • 沿着这些思路,列表项或块引用中的代码块不会被视为可执行代码。由于列表项和块引用暗示了它们自己的缩进,因此当一些代码块在这些其他块中,而另一些不在这些其他块中时,如何处理连续代码块之间的缩进将是模棱两可的。
  • 列表项最多只能有一段。列表项的第二段将在空行后缩进,因此与代码块无法区分。

源映射

CoffeeScript 包含对生成源映射的支持,这是一种告诉您的 JavaScript 引擎您的 CoffeeScript 程序的哪一部分与正在评估的代码相匹配的方法。支持它的浏览器可以自动使用源映射在调试器中显示您的原始源代码。要与您的 JavaScript 文件一起生成源映射,请将 --map-m 标志传递给编译器。

有关源映射的完整介绍,包括它们的工作原理以及如何在浏览器中连接它们,请阅读 HTML5 教程

Cake 和 Cakefiles

CoffeeScript 包含一个(非常)简单的构建系统,类似于 MakeRake。自然地,它被称为 Cake,用于构建和测试 CoffeeScript 语言本身的任务。任务在名为 Cakefile 的文件中定义,可以通过在目录中运行 cake [task] 来调用。要打印所有任务和选项的列表,只需键入 cake

任务定义是用 CoffeeScript 编写的,因此您可以在 Cakefile 中放置任意代码。使用名称、长描述和在运行任务时调用的函数来定义任务。如果您的任务需要命令行选项,您可以使用短标志和长标志来定义选项,它将在 options 对象中可用。以下是一个使用 Node.js API 重新构建 CoffeeScript 解析器的任务

如果您需要在另一个任务之前调用一个任务——例如,在 test 之前运行 build,您可以使用 invoke 函数:invoke 'build'。Cake 任务是将您的 CoffeeScript 函数公开到命令行的最小方法,因此 不要期望任何内置的奇特功能。如果您需要依赖项或异步回调,最好将它们放在代码本身中——而不是 cake 任务中。

"text/coffeescript" 脚本标签

虽然不建议用于严肃用途,但 CoffeeScript 可以使用 <script type="text/coffeescript"> 标签直接包含在浏览器中。源代码包含编译器的压缩和最小化版本(在此处下载当前版本,压缩后为 77k)作为 docs/v2/browser-compiler-legacy/coffeescript.js。在包含内联 CoffeeScript 标签的页面上包含此文件,它将按顺序编译和评估它们。

CoffeeScript 的通常注意事项适用——您的内联脚本将在闭包包装器中运行,因此如果您想公开全局变量或函数,请将它们附加到 window 对象。

集成

CoffeeScript 是庞大的 JavaScript 生态系统的一部分,许多库帮助将 CoffeeScript 与 JavaScript 集成。主要项目,尤其是更新为与 CoffeeScript 2 一起工作的项目,在此列出;更多项目可以在 维基页面 中找到。如果您认为应该将某个项目添加到本节,请打开一个问题或 拉取请求。项目按类别按字母顺序排列。

构建工具

代码编辑器

框架

代码检查器和格式化器

测试

资源

  • GitHub 上的 CoffeeScript
  • CoffeeScript 问题
    错误报告、功能建议和对语言更改的想法都属于这里。
  • CoffeeScript Google 论坛
    如果您想问问题,邮件列表是获得帮助的好地方。
  • CoffeeScript 维基
    如果您曾经学到过一些巧妙的 CoffeeScript 提示或技巧,或者遇到了一个陷阱——请在维基上分享。
  • 常见问题解答
    也许您与 CoffeeScript 相关的问题以前有人问过。请先查看常见问题解答。
  • JS2Coffee
    是一个非常棒的逆向 JavaScript 到 CoffeeScript 编译器。它不会完美(推断您的 JavaScript 类是什么,何时需要绑定函数,等等……)——但它是转换简单脚本的绝佳起点。
  • 高分辨率徽标
    CoffeeScript 的徽标以 SVG 格式提供,可用于演示文稿。

书籍

有很多优秀的资源可以帮助您开始使用 CoffeeScript,其中一些可以在线免费获取。

屏幕录像

  • CoffeeScript 简介 是一个 Code School 课程,它将 6 个屏幕录像与浏览器内编码相结合,使学习变得有趣。第一个级别可以免费试用。
  • 认识 CoffeeScript 是 PeepCode(现在是 PluralSight)制作的 75 分钟长的屏幕录像。它以动画效果而闻名,这些动画演示了将 CoffeeScript 转换为等效的 JS。
  • 如果您正在寻找时间投入较少的资源,RailsCasts 的 CoffeeScript 基础 可以满足您的需求,它将在 11 分钟内涵盖 CoffeeScript 的所有重要内容。

示例

可以在 GitHub 上找到 最佳的开源 CoffeeScript 示例列表。但只是为了再列举几个

  • GitHubHubot,一个友好的 IRC 机器人,可以执行任何数量的有用和无用的任务。
  • sstephensonPow,一个零配置 Rack 服务器,具有全面的带注释的源代码。
  • technoweenieCoffee-Resque,一个针对 Node.js 的 Resque 端口。
  • stephankOrona,一个为现代浏览器重新制作的 Bolo 坦克游戏。
  • GitHubAtom,一个基于 Web 技术的可定制文本编辑器。
  • BasecampTrix,一个用于 Web 应用程序的富文本编辑器。

网络聊天 (IRC)

通常可以在 CoffeeScript IRC 房间 #coffeescript(位于 irc.freenode.net 上)中找到快速帮助和建议,您可以 通过 Web 浏览器加入

带注释的源代码

您可以以可读的、带注释的形式浏览 CoffeeScript 2.7.0 源代码 此处。您也可以直接跳转到特定源文件

贡献

欢迎贡献!随时 fork 仓库 并提交拉取请求。

ECMAScript 的某些功能有意不支持。请查看 GitHub 上的 开放和已关闭的问题,以查看您正在寻找的功能是否已讨论过。作为一般规则,我们不支持 ECMAScript 语法,这些语法用于尚未最终确定(在 提案批准流程 中处于第 4 阶段)或在主要浏览器和/或 Node 中实现的功能(这有时会发生在处于第 3 阶段的功能上)。CoffeeScript 选择支持的任何第 3 阶段功能都应被视为实验性的,在功能达到第 4 阶段之前,可能会发生重大更改或删除。

有关向 CoffeeScript 添加内容的更多资源,请参阅 Wiki,尤其是 解析器的工作原理

您可以做几件事来提高拉取请求被接受的几率

  • 创建测试!任何拉取请求都可能需要包含基本测试,以验证您没有破坏任何东西,或者将来的更改不会破坏您的代码。
  • 遵循 CoffeeScript 代码库中其余部分的风格。
  • 确保任何 ECMAScript 语法都已成熟(处于第 4 阶段,或处于第 3 阶段,并在主要浏览器或运行时中得到支持)。
  • 仅添加具有广泛实用性的功能,而不是针对特定用例或框架的功能。

当然,您可能有一个很棒的添加,但它不符合这些约束。您可以随意创建自己的解决方案;您将 有很多同伴

不支持的 ECMAScript 功能

CoffeeScript 有意不支持一些 ECMAScript 功能。

letconst:块级作用域和重新分配保护变量

在设计 CoffeeScript 时,有意省略了 var。这是为了让开发人员免于需要担心变量声明var foo)与变量赋值foo = 1)之间的精神管理。CoffeeScript 编译器会自动为您处理声明,通过在每个函数作用域的顶部生成 var 语句。这使得意外声明全局变量成为不可能。

letconst 为 JavaScript 添加了有用的功能,您可以使用它们在作用域内声明变量,例如在 if 语句体或 for 循环体中,而 var 始终在整个函数的作用域内声明变量。在设计 CoffeeScript 2 时,人们对该功能是否足够有用以抵消 CoffeeScript 不需要考虑变量声明带来的简单性进行了很多讨论。最终,人们认为简单性更重要。在 CoffeeScript 中,只有一种类型的变量。

请记住,const 只能保护您免于重新分配变量;它不会像其他语言中的常量那样阻止变量的值发生变化。

const obj = {foo: 'bar'};
obj.foo = 'baz'; // Allowed!
obj = {}; // Throws error

命名函数和函数声明

CoffeeScript 的新手经常想知道如何生成 JavaScript function foo() {},而不是 CoffeeScript 生成的 foo = function() {}。第一种形式是 函数声明,第二种形式是 函数表达式。如上所述,在 CoffeeScript 中 一切都是表达式,因此我们自然地偏爱表达式形式。仅支持一种变体有助于避免由于 两种形式之间的细微差别而可能出现的令人困惑的错误。

从技术上讲,foo = function() {} 是创建一个匿名函数,并将其分配给名为 foo 的变量。CoffeeScript 的一些早期版本为该函数命名,例如 foo = function foo() {},但由于与 Internet Explorer 的兼容性问题,该功能被放弃了。一段时间以来,这让人们感到恼火,因为这些函数在堆栈跟踪中将是未命名的;但现代 JavaScript 运行时 从分配给它们的变量的名称推断出这些匿名函数的名称。鉴于这种情况,最简单的方法是保留当前行为。

getset 关键字简写语法

getset 作为在函数或类方法之前使用的关键字,在 CoffeeScript 中有意未实现。

这是为了避免语法歧义,因为在 CoffeeScript 中,这样的结构看起来与函数调用相同(例如 get(function foo() {}));并且因为存在 替代语法,它稍微冗长一些,但同样有效

从 CoffeeScript 1.x 到 2 的重大更改

CoffeeScript 2 旨在尽可能多地输出符合 ES2015+ 语法的代码,同时尽可能减少与 CoffeeScript 1.x 的重大更改。不幸的是,一些重大更改是不可避免的。

绑定(胖箭头)函数

在 CoffeeScript 1.x 中,=> 编译成普通的 function,但 this/@ 的引用被重写为使用外部作用域的 this,或者使用 .bind 将内部函数绑定到外部作用域(因此得名“绑定函数”)。在 CoffeeScript 2 中,=> 编译成 ES2015 的 =>,其行为略有不同。最大的区别是,在 ES2015 中,=> 函数没有 arguments 对象。

函数参数和解构元素的默认值

根据 ES2015 关于函数默认参数的规范解构默认值的规范,默认值仅在值缺失或为 undefined 时应用。在 CoffeeScript 1.x 中,默认值会在这些情况下应用,但也会在值为 null 时应用。

绑定生成器函数

绑定生成器函数,也称为生成器箭头函数,在 ECMAScript 中不允许。你可以写 function*=>,但不能同时写。因此,像这样的 CoffeeScript 代码

f = => yield this
# Throws a compiler error

需要用老式的方式重写

类被编译成 ES2015 类

ES2015 类及其方法除了对普通函数的限制外,还有一些限制。

类构造函数不能在没有 new 的情况下调用

(class)()
# Throws a TypeError at runtime

ES2015 类不允许绑定(胖箭头)方法。CoffeeScript 编译器会进行一些调整来保留对它们的 支持,但有一件事无法适应,那就是在绑定之前调用绑定方法

class Base
  constructor: ->
    @onClick()      # This works
    clickHandler = @onClick
    clickHandler()  # This throws a runtime error

class Component extends Base
  onClick: =>
    console.log 'Clicked!', @

类方法不能与 new 一起使用(不常见)

class Namespace
  @Klass = ->
new Namespace.Klass  # Throws a TypeError at runtime

由于编译成 ES2015 类需要提升,因此类方法中的动态键不能使用可执行类体中的值,除非方法以原型方式赋值。

class A
  name = 'method'
  "#{name}": ->   # This method will be named 'undefined'
  @::[name] = ->  # This will work; assigns to `A.prototype.method`

superthis

在派生类(继承自另一个类的类)的构造函数中,在调用 super 之前不能使用 this

class B extends A
  constructor: -> this  # Throws a compiler error

这也意味着你不能在派生类的构造函数中将对 this 的引用作为参数传递给 super

class B extends A
  constructor: (@arg) ->
    super @arg  # Throws a compiler error

这是 ES2015 类的限制。作为解决方法,在 super 调用之后赋值给 this

superextends

由于与带访问器的 super 存在语法冲突,“裸” super(没有括号的关键字 super)不再编译成转发所有参数的超级调用。

class B extends A
  foo: -> super
  # Throws a compiler error

可以使用 splat 显式转发参数

或者,如果你知道父函数不需要参数,只需调用 super()

CoffeeScript 1.x 允许 extends 关键字在函数之间设置原型继承,并且 super 可以用于手动原型赋值的函数

A = ->
B = ->
B extends A
B.prototype.foo = -> super arguments...
# Last two lines each throw compiler errors in CoffeeScript 2

由于切换到 ES2015 extendssuper,不再支持将这些关键字用于原型函数。上面的情况可以重构为

or

JSX 和 <> 运算符

随着 JSX 的添加,<> 字符既充当“小于”和“大于”运算符,也充当 XML 标签的定界符,例如 <div>。为了获得最佳效果,通常应始终将运算符括在空格中,以将其与 XML 标签区分开来:i < len,而不是 i<len。编译器会尽力在能够确定你的意图时宽容,但始终在“小于”和“大于”运算符周围添加空格将消除歧义。

Literate CoffeeScript 解析

CoffeeScript 2 对 Literate CoffeeScript 的解析已重构,现在更加谨慎,不会将缩进列表视为代码块;但这意味着所有代码块(除非要解释为注释)必须与列表之间至少有一行空行。

代码块现在也应该保持一致的缩进级别——因此一个制表符(或你认为是制表符停顿的任何内容,例如 2 个空格或 4 个空格)的缩进应该被视为你的代码的“左边缘”,文件中的所有代码都相对于该列。

你希望作为注释的一部分而不是执行的代码块,必须至少有一行(理想情况下是块的第一行)完全不缩进。

参数解析和 shebang(#!)行

在 CoffeeScript 1.x 中,-- 必须在要运行的脚本的路径和文件名之后,但在传递给该脚本的任何参数之前。此约定现在已弃用。因此,而不是

coffee [options] path/to/script.coffee -- [args]

现在你只需键入

coffee [options] path/to/script.coffee [args]

已弃用的版本仍然有效,但它会在运行脚本之前打印警告。

在非 Windows 平台上,可以通过在文件顶部添加 shebang(#!)行并将文件标记为可执行文件来使 .coffee 文件可执行。例如

#!/usr/bin/env coffee

x = 2 + 2
console.log x

如果将其保存为 executable.coffee,则可以使其可执行并运行

chmod +x ./executable.coffee
▶ ./executable.coffee
4

在 CoffeeScript 1.x 中,这在尝试将参数传递给脚本时会失败。OS X 上的一些用户通过使用 #!/usr/bin/env coffee -- 作为文件的第一行来解决此问题。但是,这在 Linux 上不起作用,Linux 无法解析具有多个参数的 shebang 行。虽然此类脚本仍然可以在 OS X 上运行,但 CoffeeScript 现在会在编译或评估以过长的 shebang 行开头的文件之前显示警告。现在 CoffeeScript 2 支持在不需要 -- 的情况下传递参数,我们建议简单地将此类脚本中的 shebang 行更改为 #!/usr/bin/env coffee

变更日志

2.7.0

  • 现在支持 导入断言语法。这允许像 export { version } from './package.json' assert { type: 'json' } 这样的语句,或像 import('./calendar.json', { assert { type: 'json' } }) 这样的表达式。
  • CoffeeScript 不再总是修补 Node 的错误堆栈跟踪。这种修补,其中行号和列号被调整以匹配源 CoffeeScript 而不是生成的 JavaScript,会导致与其他库发生冲突,并且在传递 Node 的新 --enable-source-maps 标志 时是不必要的。现在,修补仅在未设置 --enable-source-maps、没有其他库已修补堆栈跟踪以及使用 require('coffeescript/register') 时发生。可以通过 require('coffeescript').patchStackTrace()import { patchStackTrace } from 'coffeescript'; patchStackTrace() 显式启用修补。
  • 修复了块(三引号)字符串未正确转译成包装模板文字的 JSX 表达式容器(例如 <div a={`...`} />)的问题。
  • 修复了行延续在显式 [ 数组或 { 对象文字的第一行非空时行为不符合预期的问题。

2.6.1

  • coffeescript 包本身现在支持在 Node.js 中由 ES 模块使用时的命名导出;或者换句话说,import { compile } from 'coffeescript' 现在可以工作,而不仅仅是 import CoffeeScript from 'coffeescript'
  • 修复了在非裸模式下编译大型文件时出现的堆栈溢出错误。

2.6.0

2.5.1

  • 对象 splat 现在可以包含原型简写,例如 a = {b::c...};以及吸收,例如 a = {b?.c..., d?()...}
  • 修复了 2.5.0 中的回归,其中对于具有 Windows 风格换行符的文件,编译速度变得慢得多。
  • 修复了在较大的隐式对象中,在像 or 这样的行延续关键字之后出现隐式对象的问题。

2.5.0

  • 编译器现在支持新的ast选项,可以通过命令行上的--ast或Node API上的ast使用。此选项输出“抽象语法树”,或输入CoffeeScript源代码的JSON类表示形式。此AST尽可能遵循Babel规范,以与处理JavaScript源代码的工具兼容。使用此新AST输出的两个工具是eslint-plugin-coffee,一个通过ESLint来lint CoffeeScript的插件;以及prettier-plugin-coffeescript,一个通过Prettier来重新格式化CoffeeScript源代码的插件。CoffeeScript的AST结构和属性并非最终确定,可能会在CoffeeScript版本之间发生重大更改;如果您有兴趣创建新的集成,请打开一个问题
  • 现在CoffeeScript支持数字分隔符,语法与JavaScript相同:1_234_567
  • 现在CoffeeScript支持BigInt数字,语法与JavaScript相同:42n
  • '''"""字符串现在输出为更易读的JavaScript模板字面量,或反引号(`)字符串,带有实际的换行符,而不是\n转义序列。
  • 类现在可以包含计算属性,例如[someVar]: ->@[anotherVar]: ->
  • JSX标签现在可以包含XML样式的命名空间,例如<image xlink:href="data:image/png" /><Something:Tag></Something:Tag>
  • 修复了冒号后的注释未出现在输出中的错误;保留字错误地被禁止作为JSX属性;多行数组中缩进的引导省略;以及源映射中的无效位置数据。

2.4.1

  • CoffeeScript浏览器编译器的传统ES5现代ES模块版本现在都发布到NPM,使浏览器编译器可以通过提供NPM模块代码的公共CDN服务使用。传统版本通过package.json"browser"字段引用,ES模块版本通过"module"字段引用。

2.4.0

  • 现在支持动态import()表达式。为了与import语句区分,括号始终是必需的。请参阅模块。请注意,截至撰写本文时,JavaScript功能本身仍处于第3阶段;如果它在完全标准化之前发生更改,它也可能会在CoffeeScript中发生更改。在import()ECMAScript提案最终确定之前使用它应该被视为临时性的,如果提案发生更改或被拒绝,可能会发生重大更改。我们还修改了关于第3阶段ECMAScript功能的策略,以在这些功能在主要浏览器或Node.js等重要运行时发布时支持它们。
  • 现在有两种CoffeeScript编译器的浏览器版本:一种是多年来一直发布的传统版本,另一种是新的ES模块版本,可以通过import使用。如果您的浏览器支持它,它将在本页面上生效。package.json"module"字段中包含对ES模块浏览器编译器的引用。
  • Node API现在公开了以前私有的registerCompiled方法,以允许使用coffeescript包的插件利用CoffeeScript的内部缓存。
  • 修复了块数组中字符串中的逗号、类中do块中未维护对@的引用以及函数默认参数不应该被多余的括号包裹的错误。

2.3.2

  • 现在支持Babel 7。在版本7中,Babel团队从NPM上的babel-core迁移到@babel/core。现在CoffeeScript的--transpile选项将首先搜索@babel/core(Babel版本7及更高版本),然后搜索babel-core(版本6及更低版本),以尝试找到已安装的Babel版本以用于转译。
  • 现在支持new.target语法。
  • 您现在可以在yield关键字后跟一个缩进的object,就像已经允许return和其他关键字一样。
  • 以前,JSX标签或属性中的任何注释都会导致输出插值大括号({})。这仅对行(#,或JavaScript中的//)注释是必要的,而不是这里(###,或/* */)注释;因此,现在编译器检查所有会触发大括号的注释是否都是这里注释,如果是,则不会生成不必要的插值大括号。

2.3.1

  • 返回一个与另一个JSX标签相邻的JSX标签,而不是返回一个根JSX标签或片段,是无效的JSX语法。Babel对此抛出错误,现在CoffeeScript编译器也这样做。
  • JSX插值(<tag>{ ... }</tag>的中间)中的无效缩进现在会抛出错误。
  • 浏览器编译器,用于尝试CoffeeScript和类似的基于Web的CoffeeScript编辑器,现在在全局范围内评估代码,而不是浏览器编译器的范围内。这提高了通过浏览器编译器执行的代码的性能。
  • 语法清理:现在隐式函数调用可以接受一个无主体类作为参数,并且?::在暗示行延续方面与::的行为相同。

2.3.0

  • 此版本添加了对ES2018中所有尚未在CoffeeScript中实现的新功能和语法的支持。对于以下所有功能,请确保您转译,除非您知道您的目标运行时支持每个功能。
  • 现在支持异步迭代器。您现在可以yield一个await调用,例如do -> until file.EOF then yield await file.readLine()
  • 对象展开/解构,也称为对象剩余/展开语法,已作为ES2018的一部分标准化,因此此版本删除了以前支持此语法的polyfill。像{a, b, rest...} = obj这样的代码现在输出几乎与它出现时一样,而不是被转换为Object.assign调用。请注意,Object.assign polyfill和原生实现之间存在一些细微的差异
  • 指数运算符**和指数赋值运算符**=是ES2018中JavaScript的新增功能。现在像a ** 3这样的代码输出与它出现时一样,而不是像以前那样被转换为Math.pow(a, 3)
  • 现在在正则表达式中支持s(dotAll)标志。

2.2.4

  • for循环中的by值是字面量数字时,例如for x in [2..1] by -1,确定循环是否在范围内所需的检查更少。
  • 修复了2.2.0中的回归,其中括号内的语句,例如(fn(); break) while condition,正在编译。像breakreturn这样的纯语句不能将带括号的块转换为表达式,并且应该抛出错误。

2.2.3

  • 修复了使用空数组作为键值的object解构的错误:{ key: [] } = obj
  • 修复了将数组解构到附加到this的目标上的错误:[ @most... , @penultimate, @last ] = arr

2.2.2

  • 修复了2.2.0中的回归,其中具有与范围相反方向增量或减量的by(步长)值的范围返回一个包含范围第一个值的数组,而它应该返回一个空数组。换句话说,x for x in [2..1] by 1应该等于[],而不是[2](因为步长值为正1,向上计数,而范围从2到1,向下计数)。
  • 修复了允许importexport语句以及触发缩进块开始的行的反斜杠的错误,例如if语句。

2.2.1

  • 修复了2.2.0中的回归,其中在某些情况下,在数组中使用解构时,编译器会抛出错误。
  • 修复了2.2.0中的回归,其中在某些情况下,范围迭代器变量在全局范围内声明。

2.2.0

  • 此版本修复了所有当前打开的错误,可以追溯到2014年、2012年和2011年。
  • 潜在的破坏性更改:具有模棱两可else的内联ifswitch语句,例如if no then if yes then alert 1 else alert 2,现在编译时else始终对应于最近打开的then。以前,模棱两可else的行为是不可预测的。如果您的代码有任何if … thenswitch … then语句,其中包含多个then(以及一个或多个else),则编译后的输出现在可能不同,除非您通过括号消除了歧义。我们进行此更改是因为以前的行为不一致,基本上是一个错误:根据语法的位置,例如,如果存在内联函数或暗示块的内容,else可能会绑定到较早的then而不是较晚的then。现在,else本质上关闭了由then打开的块,类似于关闭打开的括号。
  • 当缺少必需的then时,错误会更准确地指出错误的位置。
  • coffee命令在不支持CoffeeScript编译器本身所需的某些ES2015 JavaScript功能的环境中运行时,会抛出错误。如果CoffeeScript安装在低于版本6的Node中,则可能会发生这种情况。
  • 使用非最终展开/展开的解构,例如[open, contents..., close] = tag.split(''),现在使用ES2015剩余语法输出。
  • 名为getset的函数可以在更多情况下使用,包括附加到this@?.时;或者当第一个参数是隐式对象时,例如@set key: 'val'
  • 现在可以在括号内使用诸如break之类的语句,例如(doSomething(); break) while condition(pick(key); break) for key of obj
  • 修复了在解构中为附加到this/@的属性赋值的错误,例如({@prop = yes, @otherProp = no}) ->
  • 修复了在调用super时,当参数在较低作用域中时,会抛出有关将参数附加到this的错误,例如class Child extends Parent then constructor: -> super(-> @prop)
  • 修复了当for循环被赋予一个变量来步进时,可能会导致无限循环的错误,例如for x in [1..3] by step(与by 0.5或其他原始数值相反)。
  • 修复了在评估范围时不再两次声明迭代器变量的错误,例如end = 3; fn [0..end]
  • 修复了链式调用中变量作用域错误,例如start(x = 3).then(-> x = 4)
  • 修复了传递给do的函数中变量作用域错误,例如for [1..3] then masked = 10; do -> alert masked
  • 修复了不再为函数调用中的尾随逗号抛出语法错误的错误,例如fn arg1, arg2,
  • 修复了属性访问中的表达式错误,例如a[!b in c..]
  • 修复了允许在for行中的任何位置使用行延续反斜杠(\)的错误。

2.1.1

  • 修复了为可执行类体设置正确上下文的问题。因此,在class @B extends @A then @property = 1中,@property中的@现在指的是类,而不是全局对象。
  • 修复了匿名类使用相同的自动变量名创建的问题。它们现在每个都收到唯一的名称,以免互相覆盖。

2.1.0

  • 现在支持对象字面量中的计算属性键:obj = { ['key' + i]: 42 },或obj = [Symbol.iterator]: -> yield i++
  • 现在支持数组元素的跳过,也称为省略:arr = [a, , b],或[, protocol] = url.match /^(.*):\/\//
  • JSX 片段语法 现在得到支持。
  • 修复了///块正则表达式内#行注释中的///错误地关闭正则表达式,而不是被视为注释的一部分。
  • 修复了数组解构中对象剩余解构的错误输出。

2.0.3

  • 修复了export default后跟一个包含显式对象的隐式对象,例如exportedMember: { obj... }
  • 修复了隐式对象成员后的key, val of obj,例如foo: bar for key, val of obj
  • 修复了组合数组和对象解构,例如[ ..., {a, b} ] = arr
  • 修复了一个边缘情况,在这种情况下,可以创建一个绑定(=>)生成器函数,这应该抛出错误,因为此类函数在 ES2015 中不允许。
  • 修复了源映射:.map 文件应始终与请求的输出文件名具有相同的基文件名。因此,coffee --map --output foo.js test.coffee 应生成 foo.jsfoo.js.map
  • 修复了使用 --transpile--map 编译多个输入文件时生成的错误源映射。
  • 修复了 REPL(coffee --interactive)中输入开头或结尾的注释。

2.0.2

  • --transpile 现在也适用于 requireimport 的 CoffeeScript 文件。
  • --transpile 可以与 REPL 一起使用:coffee --interactive --transpile
  • 改进了注释输出,现在应该涵盖所有 Flow 基于注释的语法。现在,变量 初始化赋值附近的内联 ### 注释将在变量声明语句中输出,并且 类和方法名称 附近的 ### 注释现在将在 Flow 预期的地方输出。
  • 现在允许导入 CoffeeScript 关键字,只要它们被别名化:import { and as andFn } from 'lib'。(你也可以执行 import lib from 'lib',然后引用 lib.and。)
  • 当给定一个无括号的对象字面量作为参数时,对名为 getset 的函数的调用不再抛出错误:obj.set propertyName: propertyValue
  • 在派生类(扩展另一个类的类)的构造函数中,你不能使用引用 this 的参数调用 superclass Child extends Parent then constructor: (@arg) -> super(@arg)。这在 JavaScript 中不允许,现在 CoffeeScript 编译器将抛出错误。相反,在调用 super 后为 this 赋值:(arg) -> super(arg); @arg = arg
  • 修复了当反引号语句和提升表达式都在同一个类体中时,输出错误的问题。这允许在同一个类中使用类似 `field = 3` 的反引号行,供使用实验性 类字段 语法的人使用,以及 CoffeeScript 输出为类原型一部分的传统类体表达式,例如 prop: 3。假设你的 转译器支持它
  • 修复了在复杂的 ? 操作之前没有输出注释的问题,例如 @a ? b
  • 所有测试现在在 Windows 中通过。

2.0.1

  • babel-core 不再列在 package.json 中,即使作为 optionalDependency,也是为了避免它被自动安装给大多数用户。如果你想使用 --transpile,只需手动安装 babel-core。参见 转译
  • --transpile 现在依赖于 Babel 来查找其选项,即正在编译的文件路径中的 .babelrc 文件。(以前 CoffeeScript 编译器正在复制此逻辑,因此从用户的角度来看没有任何变化。)这为将来版本中向 Babel 传递选项的额外方式提供了自动支持,例如 Babel 7 中即将推出的 .babelrc.js 文件。
  • 类体中的反引号表达式,在任何类方法之外,现在将在 JavaScript 类体本身中输出。这允许传递实验性 JavaScript 语法,例如 类字段提案,假设你的 转译器支持它

2.0.0

  • 添加了 --transpile 标志或 transpile Node API 选项,以告诉 CoffeeScript 编译器在保存或返回之前通过 Babel 传递其输出;参见 转译。还将 -t 短标志更改为引用 --transpile 而不是 --tokens
  • 始终填充源映射的 sourcesContent 属性。
  • 修复了解构和 JSX 中注释的错误。
  • 请注意,这些只是 2.0.0-beta5 和 2.0.0 之间的更改。有关自 1.x 以来所有更改,请参见下文。

2.0.0-beta5

  • 现在支持 Node 6,我们将尝试通过 coffee 命令或 Node API 将其作为 CoffeeScript 2 的最低要求版本维护。较旧版本的 Node 或非常青浏览器可以通过 旧版浏览器编译器 编译。
  • 命令行 --output 标志现在允许你指定输出文件名,而不仅仅是输出文件夹。
  • 命令行 --require 标志现在可以正确处理作为无效标识符的文件名或模块名(例如,NPM 模块名称中带有连字符)。
  • Object.assign(在使用对象解构时输出)使用与 Babel 输出相同的 polyfill 进行填充。这意味着除非需要对 Internet Explorer 8 或更低版本的支持(或者你自己的代码使用需要 polyfill 的功能),否则不需要 polyfill。参见 ES2015+ 输出
  • 现在输出仅包含注释的字符串或 JSX 插值("a#{### comment ###}b"<div>{### comment ###}</div>)(`a${/* comment */}b`
  • 包含引号的插值字符串(ES2015 模板字面量)不再对引号进行转义:`say "${message}"`
  • 现在可以对函数字面量进行链式操作(例如,定义一个函数,然后对其调用 .call)。
  • 当你运行 cake test 时,异步测试的结果将包含在输出中。
  • 修复了对象解构的错误;函数参数中的扩展;函数参数中生成的引用变量;do 后的链式函数;存在运算符后的 splat 吸收数组([a?.b...]);数组或函数参数中的 splat 后的尾随 if[a if b...]);尝试 throw 一个 ifforswitchwhile 或其他无效结构。
  • 修复了语法边缘情况的错误:= 和其他“表达式中间”标记后的分号;:: 后的空格;以及以 :* 开头的脚本。
  • 修复了通过 Node API 生成的源映射的错误;以及通过 Node API 从 .coffee 文件中编译 CoffeeScript 时堆栈跟踪行号的错误。

2.0.0-beta4

  • 此版本包含 1.12.6 到 1.12.7 的所有更改
  • 行注释(以 # 开头)现在将在生成的 JavaScript 中输出。
  • 块注释(由 ### 分隔)现在允许在任何地方使用,包括以前不可能的内联位置。这为使用 Flow 的基于注释的语法提供对 静态类型注释 的支持。
  • 现在支持 JSX 标签中的扩展语法(... 用于对象):<div {props...} />
  • 改进了通过 coffee 运行的脚本的参数解析。参见 重大更改
  • CLI:在 node 被 fork 时传播 SIGINTSIGTERM 信号。
  • REPL 中现在允许使用 await,无需包装函数。
  • 现在允许使用 do super,并且其他对 super 的访问,例如 super.x.ysuper['x'].y 现在可以正常工作。
  • 现在允许在左侧或右侧使用 splat/扩展语法三个点(因此 props......props 都有效)。
  • 标记模板字面量被识别为可调用函数。
  • 修复了嵌套属性中对象扩展语法的错误。
  • 修复了解构的函数参数默认值的问题。

2.0.0-beta3

  • JSX 现在得到支持。
  • 对象剩余/扩展属性 现在得到支持。
  • 绑定(胖箭头)方法再次在类中得到支持;但是,如果你尝试在绑定方法之前调用它,则会抛出错误。参见 类重大更改
  • REPL 不再警告为 _ 赋值。
  • 修复了解构的嵌套默认值和与跨多行链式操作或继续表达式相关的错误。

2.0.0-beta2

  • 此版本包含 1.12.5 到 1.12.6 的所有更改
  • 类中的绑定(胖箭头)方法必须在类构造函数中声明,如果类扩展了父类,则在super()之后声明。请参阅类中的重大变更
  • 所有不必要的实用程序辅助函数已被删除,包括indexOfbind的多态填充。
  • extends关键字现在仅在类的上下文中有效;它不能用于扩展函数原型。请参阅extends的重大变更
  • Literate CoffeeScript现在完全基于缩进进行解析,类似于1.x实现;不再依赖于解析Markdown。请参阅Literate CoffeeScript解析的重大变更
  • 用作属性的JavaScript保留字不再用引号括起来。
  • require('coffeescript')现在应该在非Node环境中工作,例如Webpack或Browserify创建的构建。这提供了一种更方便的方法,可以在打算在浏览器环境中运行的构建中包含浏览器编译器。
  • throw异常的switch case之后不再添加不可达的break语句。
  • 浏览器编译器现在使用Babili编译,并转译为Babel的env预设(应该可以安全地用于当前所有浏览器,而不仅仅是常青版本)。
  • 调用函数@get@set不再抛出关于所需括号的错误。(裸getset,不附加到对象或@仍然故意抛出编译器错误)。
  • 如果设置了$XDG_CACHE_HOME,REPL .coffee_history文件将保存在那里。

2.0.0-beta1

  • CoffeeScript 2的第一个beta版本。预计不会再有重大变更。
  • 解构的对象和数组现在尽可能使用ES2015+语法输出。
  • Literate CoffeeScript现在对解析Markdown有更好的支持,这得益于使用Markdown-It来检测Markdown部分,而不是仅仅查看缩进。
  • 调用名为getset的函数现在需要括号,以区分getset关键字(它们是不允许的)。
  • 编译器现在需要Node 7.6+,这是Node的第一个版本,它支持异步函数,而无需任何标志。

2.0.0-alpha1

  • CoffeeScript 2的第一个alpha版本。CoffeeScript编译器现在尽可能输出ES2015+语法。请参阅重大变更
  • 类使用ES2015 classextends关键字输出。
  • 添加了对async/await的支持。
  • 绑定(箭头)函数现在输出为=>函数。
  • 具有默认值的函数参数现在使用ES2015默认值语法。
  • Splat函数参数现在使用ES2015扩展语法。
  • 计算属性现在使用ES2015语法。
  • 插值字符串(模板字面量)现在使用ES2015反引号语法。
  • 改进了对Literate CoffeeScript文件中识别Markdown的支持。
  • 现在不允许在缩进中混合制表符和空格。
  • 浏览器编译器现在使用Google Closure Compiler(JavaScript版本)进行压缩。
  • CoffeeScript 2需要Node 7+。

1.12.7

  • 修复了1.12.6中与链式函数调用以及缩进的returnthrow参数相关的回归。
  • REPL 不再警告为 _ 赋值。

1.12.6

  • returnexport关键字现在可以接受隐式对象(通过缩进定义,无需大括号)。
  • 支持Unicode代码点转义(例如\u{1F4A9})。
  • coffee命令现在首先查看CoffeeScript是否安装在当前文件夹的node_modules下,如果安装了,则执行那里的coffee二进制文件;否则,它将运行全局安装的二进制文件。这允许您在全局安装一个版本的CoffeeScript,并在特定项目中安装另一个版本。(cake命令也是如此)。
  • 修复了链式函数调用未关闭隐式对象或三元运算符的错误。
  • 修复了三元if语句中?运算符生成的代码不正确的错误。
  • 修复了一些测试,现在失败的测试将导致非零退出代码。

1.12.5

  • 更好地处理importexport语句中的defaultfromas*。您现在可以导入或导出名为default的成员,编译器不会将其解释为default关键字。
  • 修复了无效的八进制转义序列在编译器中未抛出错误的错误。

1.12.4

  • cake命令已更新,大多数任务都有新的watch选项。克隆CoffeeScript仓库并在仓库根目录运行cake以查看选项。
  • 修复了export引用变量阻止变量声明的错误。
  • 修复了coffee命令对.litcoffee文件不起作用的错误。
  • 修复了与标记和位置数据相关的错误,以获得更好的源映射并提高与下游工具的兼容性。

1.12.3

  • @值现在可以在for表达式中用作索引。这放宽了for表达式的编译,允许索引变量为@值,例如do @visit for @node, @index in nodes。在@visit中,当前节点(@node)的索引将作为@index可用。
  • CoffeeScript的修补的Error.prepareStackTrace已恢复,并进行了一些修改,这些修改应该可以防止导致一些下游项目出现错误异常的错误异常。这修复了自1.12.2以来堆栈跟踪中的错误行号。
  • //=运算符的输出现在将括号包装在右操作数周围,就像其他赋值运算符一样。

1.12.2

  • 浏览器编译器可以通过MINIFY=false cake build:browser再次构建为未压缩版本。
  • 已删除易于出错的修补版本Error.prepareStackTrace
  • REPL中的命令完成(按Tab键获取建议)已针对Node 6.9.1+修复。
  • 基于浏览器的测试现在包含所有与基于Node的版本相同的测试。

1.12.1

  • 您现在可以导入名为default的模块成员,例如import { default } from 'lib'。尽管与ES2015一样,您不能导入整个模块并将其命名为default(因此import default from 'lib'是不允许的)。
  • 修复了from作为变量名导致for循环声明失败的回归。为了记录,from不是CoffeeScript中的保留字;您可以将其用于变量名。fromimportexport语句的上下文中以及在for循环的声明中表现得像关键字一样;尽管您也应该能够在这些上下文中使用名为from的变量,并且编译器应该能够区分它们。

1.12.0

  • CoffeeScript现在支持ES2015 标记的模板字面量。请注意,在代码中使用标记的模板字面量意味着您有责任确保您的运行时支持标记的模板字面量,或者您将输出的JavaScript进一步转译为目标运行时支持的版本。
  • CoffeeScript现在提供了一种for…from语法,用于输出ES2015 for…of。(很抱歉它们不匹配,但我们首先为其他内容提出了for…of)。这允许迭代生成器或任何其他可迭代对象。请注意,在代码中使用for…from意味着您有责任确保您的运行时支持for…of,或者您将输出的JavaScript进一步转译为目标运行时支持的版本。
  • 三个反引号( ```​)允许创建嵌入式JavaScript块,其中不需要转义单个反引号,这应该可以提高与ES2015模板字面量和Markdown的互操作性。
  • 在单个反引号嵌入式JavaScript中,反引号现在可以通过 \`​转义。
  • 浏览器测试现在再次在浏览器中运行,如果您想测试您的浏览器,可以在这里访问它们。
  • ES2015 importexport中的CoffeeScript专用关键字现在被忽略。
  • 编译器现在在尝试导出匿名类时抛出错误。
  • 修复了与标记和位置数据相关的错误,以获得更好的源映射并提高与下游工具的兼容性。

1.11.1

  • 修复了插值键后简写对象语法的错误。
  • 修复了"""字符串中缩进剥离的错误。
  • 修复了无法将“arguments”用作类的原型属性名称的错误。
  • 将大型十六进制数字字面量正确编译为2e308(就像所有其他大型数字字面量一样)。

1.11.0

  • CoffeeScript现在支持ES2015 importexport语法
  • 向编译器添加了-M, --inline-map标志,允许您将源映射直接嵌入到输出的JavaScript中,而不是作为单独的文件。
  • 修复了yield的许多错误
    • yield return不再可以错误地用作表达式。
    • yield现在与return类似,它可以独立使用,也可以与表达式一起使用。以前您写的是yield undefined,现在您可以简单地写yield。但是,这意味着也继承了return相同的语法限制,因此以下示例不再编译
      doubles = ->
        yield for i in [1..3]
          i * 2
      six = ->
        yield
          2 * 3
      
    • JavaScript输出更漂亮,不再存在不必要的括号和空格、双重缩进以及yield周围的双分号。
  • &&=||=and=or=不再意外地允许等号之前有空格。
  • 改进了几个错误消息。
  • 就像undefined编译为void 0一样,NaN现在编译为0/0Infinity编译为2e308
  • 修复了重命名带默认值的解构参数的错误。({a: b = 1}) -> 不会再导致编译器崩溃。
  • 改进了 CoffeeScript 程序的内部表示。这只会影响使用 CoffeeScript.tokensCoffeeScript.nodes 的工具。此类工具需要更新以适应更改或添加的标记和节点。
  • 修复了几个小错误,包括
    • catch 块中捕获的错误不再被不必要地声明,并且对于没有 catchtry 块,不再错误地命名为 undefined
    • 不可赋值的参数解构不再导致编译器崩溃。
    • 源映射现在被正确地用于从 .coffee.md 文件抛出的错误。
    • coffee -e 'throw null' 不再崩溃。
    • REPL 在使用 .exit 退出时不再崩溃。
    • 当在同一作用域中使用大量 for 循环时,不再输出无效的 JavaScript 代码。
    • 使用 CLI 与 stdin 时的 Unicode 问题。

1.10.0

  • CoffeeScript 现在支持 ES2015 风格的解构默认值。
  • (offsetHeight: height) -> 无法再编译。该语法是意外的,并且部分失效。请改用 ({offsetHeight: height}) ->。对象解构始终需要花括号。
  • 修复了几个小错误,包括
    • 修复了 REPL 有时会根据之前输入的内容将有效代码报告为无效代码的错误。
    • 修复了 jest 测试框架中多个 JS 上下文的问题。
    • 修复了 io.js 中在内部模块上设置严格模式的错误。
    • 修复了 catch 块中捕获的错误的变量名冲突。

1.9.3

  • 修复了隐式调用中对象字面量第一个键的插值错误。
  • 修复了 REPL 中的错误消息,以及 REPL 的一些小错误。
  • 修复了使用 --bare 选项编译时,行首标记的源映射问题。这也有助于生成更小的源映射。
  • 对编译后的块注释进行了轻微的格式改进。
  • onoffyesno 提供了更好的错误消息。

1.9.2

  • 修复了 1.9.1 中引入的,在编译具有相同文件名的多个文件时出现的 watch 模式错误。
  • 修复了包含 this 的表达式周围的 yield 错误。
  • 向 REPL 添加了 Ruby 风格的 -r 选项,允许在使用 --eval--interactive 执行之前,先引入模块。
  • <script type="text/coffeescript"> 标签中,为了避免可能对 .coffee 文件的重复浏览器请求,现在可以使用 data-src 属性代替 src
  • 修复了 IE8、严格 ES5 正则表达式和 Browserify 的一些小错误。

1.9.1

  • 插值现在可以在对象字面量键中使用(再次)。你可以使用它来动态命名属性。
  • 内部编译器变量名不再以下划线开头。这使得生成的 JavaScript 代码更漂亮,并且还修复了 AngularJS “解析”函数参数的完全错误和糟糕的方式。
  • 修复了与 yield returnyield throw 相关的几个 yield 边缘情况。
  • 修复了一些小错误,并对编译器错误消息进行了各种改进。

1.9.0

  • CoffeeScript 现在支持 ES2015 生成器。生成器只是一个 yield 的函数。
  • 更强大的解析和改进的字符串和正则表达式错误消息 - 特别是关于插值的错误消息。
  • 更改了内部编译器变量名生成的策略。请注意,这意味着 @example 函数参数不再作为裸 example 变量在函数体中可用。
  • 修复了 REPL 与最新版本的 Node 和 Io.js 的兼容性。
  • 修复了各种小错误。

1.8.0

  • CLI 的 --join 选项现在已弃用。
  • 源映射现在使用 .js.map 作为文件扩展名,而不是 .map
  • CLI 现在在无法将文件写入磁盘时,以退出代码 1 退出。
  • 编译器不再在未终止的单引号字符串上崩溃。
  • 修复了字符串插值的定位数据,这使得源映射不同步。
  • 如果代码使用制表符缩进,错误消息中的错误标记现在将被正确地定位。
  • 修复了 CoffeeScript 的源映射修补的堆栈跟踪中出现的轻微格式错误。
  • %% 运算符现在只强制转换其右操作数一次。
  • 现在可以从 Cakefiles 中引入 CoffeeScript 文件,而无需先注册编译器。
  • CoffeeScript REPL 现在被导出,可以使用 require 'coffeescript/repl' 引入。
  • 修复了 Node 0.11 中的 REPL 问题。

1.7.1

  • 修复了使用 coffee 二进制文件直接运行脚本时,导致节点模块查找失败的拼写错误。

1.7.0

  • 在 Node 中引入 CoffeeScript 文件时,现在必须显式注册编译器。这可以通过 require 'coffeescript/register'CoffeeScript.register() 完成。对于 Mocha 等配置,也请使用 coffeescript/register
  • 改进了错误消息、源映射和堆栈跟踪。源映射现在使用更新的 //# 语法。
  • 前导 . 现在将关闭所有打开的调用,从而允许更简单的链式语法。
  • 添加了 **//%% 运算符,以及参数列表和解构表达式中的 ... 展开。
  • 多行字符串现在由单个空格连接,并忽略所有缩进。行尾的反斜杠可以表示行间空格的数量,无论是在字符串中还是在 heredocs 中。反斜杠在块正则表达式中正确地转义空格。
  • 现在可以缩进闭合括号,因此不再会导致意外错误。
  • 修复了几个编译错误。不可调用的字面量(字符串、数字等)现在无法在调用中编译,并且多个后缀条件语句可以正确编译。后缀条件语句和循环始终绑定对象字面量。条件赋值在子表达式中可以正确编译。super 在方法之外不允许使用,并且在 for 循环内部可以正确使用。
  • 改进了编译后的块注释的格式。
  • Windows 上不再有 -p 文件夹。
  • 传递给 CoffeeScript 的 options 对象不再被修改。

1.6.3

  • CoffeeScript REPL 现在可以记住会话之间的历史记录。就像一个真正的 REPL 应该做的那样。
  • 现在可以在 Node 中使用 require 来加载 .coffee.md 文学 CoffeeScript 文件。在浏览器中,可以使用 text/literate-coffeescript 脚本标签。
  • 旧的 coffee --lint 命令已被删除。它在最初开发编译器时很有用,但已经被 JSHint 超越。现在可以使用 -l 将文学文件通过 stdio 传递。
  • 修复了 Windows 路径分隔符、不命名错误的 catch 以及带有原型属性附加的执行类体的问题。

1.6.2

  • 源映射已被用于在通过 coffee 命令直接运行 CoffeeScript 时提供自动行映射,以及在浏览器中直接运行 CoffeeScript 时提供自动行映射。此外,还用于为编译器抛出的语义错误提供更好的错误消息 - 甚至带有颜色
  • 改进了对混合文学/普通风格 CoffeeScript 项目的支持,以及同时为两者生成源映射。
  • 修复了 1.6.x 中关于覆盖继承的绑定函数的回归,以及 Windows 文件路径管理的问题。
  • coffee 命令现在可以正确地 fork() .coffee.js 文件。(需要 Node.js 0.9+)

1.6.1

  • 首次发布了 源映射。向编译器传递 --map 标志,然后就可以开始使用了。感谢 Jason Walton 的贡献。
  • 修复了 1.5.0 中关于对缩进的隐式对象进行多次隐式调用的回归。隐式函数调用和隐式对象的组合现在通常应该被解析得更好 - 但将它们嵌套得太深仍然不是好 风格
  • .coffee.md 现在也被支持作为文学 CoffeeScript 文件扩展名,用于现有的工具。.litcoffee 仍然是规范的扩展名。
  • 修复了与类声明中的成员属性、绑定方法和 super 相关的几个小错误。

1.5.0

  • 首次发布了 文学 CoffeeScript
  • CoffeeScript REPL 现在基于 Node.js REPL,应该能够更好地工作,并且更加熟悉。
  • 现在禁止从构造函数中返回显式值。如果你想返回任意值,请使用函数,而不是构造函数。
  • 现在可以反向遍历数组,而无需手动处理索引:for item in list by -1
  • 源位置现在保存在 CoffeeScript AST 中,但尚未发出源映射。

1.4.0

  • CoffeeScript 编译器现在会剥离 Microsoft 的 UTF-8 BOM(如果存在),允许你编译带有 BOM 的源文件。
  • 通过删除 registerExtension,以及从 path.exists 迁移到 fs.exists,修复了 Node/编译器弃用警告。
  • 对 splat 编译、反引号、切片以及对象字面量中重复键的错误进行了少量调整。

1.3.3

  • 由于 JavaScript 严格模式的新语义,CoffeeScript 不再保证构造函数在所有运行时都有名称。有关讨论,请参阅 #2052
  • 在实例方法内部的嵌套函数中,现在可以更可靠地调用 super(递归向上遍历)。
  • 命名的循环变量不再具有与其他局部变量不同的作用域启发式方法。(恢复 #643)
  • 修复了解构赋值的 LHS 中嵌套的 splat 问题。
  • 对编译时严格模式禁止八进制字面量的修正。

1.3.1

  • CoffeeScript 现在在编译时强制执行 JavaScript 的所有 严格模式 早期语法错误。这包括旧式八进制字面量、对象字面量中的重复属性名、函数定义中的重复参数、删除裸变量、设置 evalarguments 的值等等。有关完整讨论,请参阅 #1547
  • REPL 现在有一个方便的新多行模式,用于输入大型代码块。在将示例复制粘贴到 REPL 时,它很有用。使用 Ctrl-V 进入多行模式。现在也可以将输入直接管道到 REPL 中。
  • CoffeeScript 现在在每个编译文件的顶部打印一个 Generated by CoffeeScript VERSION 标头。
  • 先前未定义变量的条件赋值 a or= b 现在被视为语法错误。
  • do 语义的调整,现在可以使用它更轻松地模拟命名空间:do (x = 1, y = 2) -> …
  • 循环索引现在在循环迭代中是可变的,在迭代之间是不可变的。
  • 现在允许省略切片的两个端点以保持一致性,从而有效地创建列表的浅拷贝。
  • 对 Node 的“新”文件监视 API 中的 coffee --watch 进行了额外的调整和改进。如果在监视的脚本中引入语法错误,Watch 现在默认会发出蜂鸣声。在递归监视时,我们现在还默认忽略隐藏目录。

1.2.0

  • coffee --watch--join 进行了多项改进。您现在可以将两者一起使用,以及在 --watch 的文件夹中添加和删除文件和目录。
  • throw 语句现在可以作为表达式的一部分使用。
  • 文件顶部的块注释现在将出现在安全闭包包装器之外。
  • 修复了与尾随运算符和未完成行有关的许多 1.1.3 回归,以及一个更主要的 1.1.3 回归,该回归导致绑定类函数内部的绑定函数具有不正确的 this

1.1.3

  • 啊,空格。CoffeeScript 编译的 JS 现在尝试将内容隔开并保持可读性,如您在本页的示例中所见。
  • 您现在可以在类主体中的类级别方法中调用 super,并且绑定类方法现在保留其正确的上下文。
  • JavaScript 一直支持八进制数 010 is 8 和十六进制数 0xf is 15,但 CoffeeScript 现在也支持二进制数:0b10 is 2
  • CoffeeScript 模块已嵌套在子目录下,以便更轻松地单独 require 各个组件,而无需使用 npm。例如,在将 CoffeeScript 文件夹添加到您的路径后:require('coffeescript/lexer')
  • 在本网页上的 Try CoffeeScript 中有一个新的“链接”功能。使用它来获取示例脚本的可共享永久链接。
  • coffee --watch 功能现在仅适用于 Node.js 0.6.0 及更高版本,但现在也适用于 Windows。
  • 来自 @michaelficarra@geraldalewis@satyr@trevorburnham 的许多小错误修复。

1.1.2

修复了块注释格式、?= 编译、针对控制结构的隐式调用、try/catch 块的隐式调用、从局部作用域泄漏的可变参数、heregexes 后的语法错误中的行号、带括号的数字文字上的属性访问、绑定类方法和带有保留名称的 super、REPL 大修、连续编译的分号、隐式调用对象中的块注释以及 Chrome 错误。

1.1.1

用于具有外部构造函数的类的错误修复版本,请参阅问题 #1182。

1.1.0

通过 coffee 可执行文件运行时,process.argv 及其朋友现在报告 coffee 而不是 node。与 Node.js 0.4.x 模块查找更改的更好的兼容性。REPL 中的输出现在是彩色的,就像 Node 的一样。使用 --join 时,现在必须为您的连接的 CoffeeScripts 指定名称。修复了意外地将复合除法 /= 解析为正则表达式。现在,所有 text/coffeescript 标签都应按其包含的顺序执行。修复了使用外部构造函数的扩展子类的问题。修复了 addImplicitParentheses 中的边缘情况无限循环。修复了长函数调用链的指数级减速。全局变量不再泄漏到 CoffeeScript REPL 中。扩展参数被声明为函数的局部变量。

1.0.1

修复了 Unicode 标识符的词法分析器错误。更新了 REPL 以与 Node.js 0.3.7 兼容。修复了在 REPL 中需要相对路径。现在优化了尾随 returnreturn undefined。停止需要核心 Node.js util 模块以向后兼容 Node.js 0.2.5。修复了条件 return 会导致 switch 语句中出现贯穿的情况。优化了解构赋值中的空对象。

1.0.0

CoffeeScript 循环不再尝试在循环主体中生成函数时保留块作用域。相反,您可以使用 do 关键字来创建一个方便的闭包包装器。添加了一个 --nodejs 标志,用于将选项直接传递给 node 可执行文件。在表达式中使用纯语句时,行为更好。修复了所有浏览器的 -1 的包含切片,以及使用任意表达式作为端点的拼接。

0.9.6

REPL 现在正确地格式化堆栈跟踪,并在异步异常时保持活动状态。使用 --watch 现在会在编译文件时打印时间戳。修复了在提取的闭包循环中意外泄漏的一些变量。构造函数现在在类主体中保持其声明位置。动态对象键已被删除。现在支持嵌套类。修复了裸扩展函数的执行上下文。修复了链式比较的反转。链式类实例化现在可以与扩展一起正常工作。

0.9.5

0.9.5 应被视为 CoffeeScript 1.0 的第一个发布候选版本。自上一个版本以来,已经进行了大量的内部更改,其中许多来自 satyrCoco CoffeeScript 方言。添加了 Heregexes(扩展正则表达式)。函数现在可以具有默认参数。类主体现在是可执行代码。改进了无效 CoffeeScript 的语法错误。undefined 现在像 null 一样工作,并且不能被分配新值。在单行理解方面存在优先级更改:result = i for i in list 以前默认解析为 result = (i for i in list)……现在解析为 (result = i) for i in list

0.9.4

CoffeeScript 现在使用适当命名的临时变量,并在使用后回收其引用。添加了对 Node.js 0.3require.extensions 支持。在浏览器中加载 CoffeeScript 现在只向全局作用域添加一个 CoffeeScript 对象。修复了隐式对象和块注释边缘情况。

0.9.3

CoffeeScript switch 语句现在编译成 JS switch 语句——它们以前编译成 if/else 链以兼容 JavaScript 1.3。现在支持浸泡函数调用。RubyMine 编辑器的用户现在应该能够使用 --watch 模式。

0.9.2

现在可以省略范围文字的开始和结束,例如 array[3..]。您现在可以说 a not instanceof b。修复了嵌套的显着和非显着缩进的重要错误(问题 #637)。添加了一个 --require 标志,允许您挂钩到 coffee 命令。添加了我们首选的 JavaScriptLint 设置的自定义 jsl.conf 文件。通过为操作扁平化规则,加快了 Jison 语法编译时间。块注释现在可以与 JavaScript 最小化器友好的语法一起使用。添加了 JavaScript 的复合赋值按位运算符。修复了具有前导数字和字符串键的隐式对象文字的错误,作为隐式调用的主题,以及作为复合赋值的一部分。

0.9.1

0.9.1 的错误修复版本。极大地改进了混合隐式对象、隐式函数调用和隐式缩进的处理。字符串和正则表达式插值现在严格为 #{ … }(Ruby 风格)。编译器现在接受 --require 标志,该标志指定在编译之前运行的脚本。

0.9.0

CoffeeScript 0.9 系列被认为是 1.0 的发布候选版本;让我们给她进行一次试航。0.9.0 引入了一个巨大的向后不兼容的更改:赋值现在使用 =,对象文字使用 :,就像在 JavaScript 中一样。这使我们能够拥有隐式对象文字和 YAML 风格的对象定义。半赋值被删除,取而代之的是 +=or= 等。插值现在使用井号 # 而不是美元符号 $——因为美元符号可能是有效 JS 标识符的一部分。向下范围理解现在再次安全,并且在使用整数端点创建时被优化为直接 for 循环。添加了一种快速、无保护的对象理解形式:for all key, value of object。在没有参数的情况下提及 super 关键字现在会转发传递给函数的所有参数,就像在 Ruby 中一样。如果您从父类 A 扩展类 B,如果 A 定义了 extended 方法,它将被调用,并将 B 传递给它——这在其他方面启用了静态继承。使用粗箭头绑定的函数的更清晰输出。@variables 现在可以在参数列表中使用,参数将自动设置为对象的属性——这在构造函数和 setter 函数中很有用。构造函数现在可以接受扩展。

0.7.2

快速修复(紧随 0.7.1 之后)一个问题,该问题在某些情况下阻止了 coffee 命令行选项的解析。

0.7.1

现在块级注释将被传递并作为 JavaScript 块级注释打印 - 使它们可用于许可证和版权页眉。更好地支持通过哈希邦独立运行 CoffeeScript 脚本。改进对不在语法中的标记的语法错误。

0.7.0

CoffeeScript 变量风格现在是 camelCase,与 JavaScript 一致。现在允许使用保留字作为对象键,并将为您引用它们。范围推导现在生成更简洁的代码,但如果您想向下迭代,则必须指定 by -1。与之前的版本相比,语法错误的报告得到了极大的改进。现在,在没有参数的情况下运行 coffee 将启动 REPL,并支持 Readline。<- 绑定运算符已从 CoffeeScript 中删除。添加了 loop 关键字,它等效于 while true 循环。包含闭包的推导现在将像 forEach 的语义一样闭包其变量。现在可以在类定义中使用绑定函数(绑定到实例)。为了保持一致性,a in b 现在是数组存在检查,而 a of b 是对象键检查。注释不再传递到生成的 JavaScript 中。

0.6.2

coffee 命令现在将在编译包含脚本的目录时保留目录结构。修复了两个阻止 CoffeeScript 编译器在 Internet Explorer 中实时运行的遗漏。现在有一个块注释语法,类似于 CoffeeScript 的 heredocs。现在支持 ECMA Harmony DRY 风格的模式匹配,其中属性的名称与值的名称相同:{name, length}: func。现在允许在推导变量中进行模式匹配。现在允许在块形式中使用 unless。添加了 until 循环,作为 while 循环的反面。现在允许在没有 switch 对象子句的情况下使用 switch 语句。与 Node.js v0.1.95 兼容。

0.6.1

升级 CoffeeScript 以与新的 Node.js v0.1.90 系列兼容。

0.6.0

现在允许使用尾随逗号,类似于 Python。可以使用 @property 符号在类定义中直接分配静态属性。

0.5.6

现在可以在正则表达式和 heredocs 以及字符串中使用插值。添加了 <- 绑定运算符。允许将赋值分配给半表达式,而不是特殊的 ||= 风格的运算符。arguments 对象不再自动转换为数组。在要求 coffeescript 之后,Node.js 现在可以直接加载 .coffee 文件,这要归功于 registerExtension。现在可以在函数调用、数组和模式匹配中使用多个 splat。

0.5.5

字符串插值,由 Stan Angeloff 贡献。由于 --run0.5.3 以来一直是默认值,因此更新 --stdio--eval 以默认情况下运行,如果您想打印结果,请也传递 --compile

0.5.4

修复了纠正 Node.js 全局常量 __filename__dirname 的错误。调整以更灵活地解析嵌套函数字面量和格式不正确的缩进注释。更新以适应最新的 Node.js API。

0.5.3

CoffeeScript 现在有一个定义类的语法。许多核心组件(节点、词法分析器、重写器、作用域、Optparse)都在使用它们。Cakefiles 可以使用 optparse.coffee 来定义任务的选项。--run 现在是 coffee 命令的默认标志,使用 --compile 保存 JavaScripts。修复了正则表达式字面量和链式除法之间的歧义错误。

0.5.2

添加了一个压缩版本的编译器,用于包含在网页中,作为 /v2/browser-compiler-legacy/coffeescript.js。它将自动运行任何类型为 text/coffeescript 的脚本标签。在 coffee 命令中添加了一个 --stdio 选项,用于管道输入编译。

0.5.1

对使用存在运算符的空值吸收进行了改进,包括对索引属性的吸收。在 while 循环中添加了条件,因此您可以像推导一样使用 when 将它们用作过滤器。

0.5.0

CoffeeScript 0.5.0 是一个主要版本,虽然没有语言更改,但 Ruby 编译器已被删除,取而代之的是用纯 CoffeeScript 编写的自托管编译器。

0.3.2

@property 现在是 this.property 的简写。将默认的 JavaScript 引擎从 Narwhal 切换到 Node.js。如果您想继续使用它,请传递 --narwhal 标志。

0.3.0

CoffeeScript 0.3 包含主要的语法更改:函数符号已更改为 ->,绑定函数符号现在是 =>。函数定义中的参数列表现在必须用括号括起来。添加了属性吸收,使用 ?. 运算符。在使用参数调用函数时,使括号可选。删除了过时的块字面量语法。

0.2.6

添加了 Python 风格的链式比较、条件存在运算符 ?= 以及来自 Beautiful Code 的一些示例。与语句到表达式转换、参数到数组转换以及 TextMate 语法高亮相关的错误修复。

0.2.5

switch 语句中的条件现在可以同时接受多个值 - 如果其中任何一个为真,则 case 将运行。添加了长箭头 ==>,它定义并立即将函数绑定到 this。现在可以像推导一样使用 while 循环作为表达式。可以在模式匹配中使用 splat 来吸收数组的其余部分。

0.2.4

添加了 ECMAScript Harmony 风格的解构赋值,用于处理从嵌套数组和对象中提取值。添加了缩进敏感的 heredocs,用于格式良好的字符串或代码块。

0.2.3

删除了令人不快的 ino 关键字,用 of 替换它,用于对象推导。它们现在看起来像:for prop, value of object

0.2.2

在对对象执行推导时,使用 ino 而不是 in,这有助于我们在编译时生成更小、更高效的代码。添加了 :: 作为 .prototype. 的简写。“splat” 符号已从前缀星号 * 更改为后缀省略号 ... 添加了 JavaScript 的 in 运算符、空 return 语句和空 while 循环。以大写字母开头的构造函数现在包含一个安全检查,以确保返回对象的新的实例。extends 关键字现在与 Google 的 Closure 库中的 goog.inherits 功能相同。

0.2.1

现在将 arguments 对象转换为引用时的真实数组。

0.2.0

主要版本。显著的空白。更好的语句到表达式转换。Splats。Splice 字面量。对象推导。块。存在运算符。感谢所有发布问题的人,特别感谢 Liam O’Connor-Davis 提供空白和表达式帮助。

0.1.6

修复了从 CoffeeScript 目录外部运行 coffee --interactive--run 的错误。修复了嵌套函数/if 语句的错误。

0.1.5

数组切片字面量和数组推导现在都可以使用 Ruby 风格的范围来指定开始和结束。JavaScript 变量声明现在被推到作用域的顶部,使所有赋值语句成为表达式。您可以使用 \ 来转义换行符。coffeescript 命令现在称为 coffee

0.1.4

官方 CoffeeScript 扩展现在是 .coffee 而不是 .cs,后者属于 C#。应广大需求,您现在也可以使用 = 来赋值。与 JavaScript 不同,= 也可以在对象字面量中使用,与 : 可互换。对像 func(1)(2)(3)(4) 这样的链式函数调用的语法进行了修正。继承和 super 不再使用 __proto__,因此它们现在应该与 IE 兼容。

0.1.3

coffee 命令现在包含 --interactive,它启动一个交互式的 CoffeeScript 会话,以及 --run,它直接编译并执行脚本。这两个选项都依赖于 Narwhal 的正常安装。aint 关键字已被 isnt 替换,它与 is 更为协调。现在允许在对象字面量中使用引号字符串作为标识符:例如 {"5+5": 10}。所有赋值运算符现在都使用冒号:+:-:*: 等。

0.1.2

修复了通过多个继承级别调用 super() 的错误,并重新添加了 extends 关键字。添加了对实验性 Narwhal 支持(作为 Tusk 包),由 Tom Robinson 贡献,包括 bin/cs 作为 CoffeeScript REPL 和解释器。新的 --no-wrap 选项用于抑制安全函数包装器。

0.1.1

添加了 instanceoftypeof 作为运算符。

0.1.0

CoffeeScript 首次发布。