CoffeeScript 是一種編譯成 JavaScript 的小型語言。在笨拙的 Java 風格外皮之下,JavaScript 一直擁有一顆美麗的心。CoffeeScript 嘗試以簡單的方式呈現 JavaScript 的優點。

CoffeeScript 的黃金法則為:「它只是 JavaScript」。程式碼會一對一編譯成等效的 JS,且執行期間不會進行任何詮釋。您可以從 CoffeeScript 無縫使用任何現有的 JavaScript 函式庫(反之亦然)。編譯輸出的可讀性高、排版美觀,且執行速度往往與等效的手寫 JavaScript 一樣快,甚至更快。

CoffeeScript 編譯器會盡力產生可在所有 JavaScript 執行環境中執行的輸出 JavaScript,但仍有例外。僅在您知道 目標執行環境支援 的情況下,才使用 產生器函式for…from標記範本字串。如果您使用 模組,則需要 使用其他工具來解析它們

最新 1.x 版本: 1.12.7

npm install -g coffeescript

升級到 CoffeeScript 2! 它增加了對 ES2015 類別async/awaitJSX物件 rest/spread 語法,以及 使用現代語法產生的 JavaScript 的支援。 了解更多

概觀

左邊是 CoffeeScript,右邊是編譯後的 JavaScript 輸出。

# Assignment:
number   = 42
opposite = true

# Conditions:
number = -42 if opposite

# Functions:
square = (x) -> x * x

# Arrays:
list = [1, 2, 3, 4, 5]

# Objects:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# Existence:
alert "I knew it!" if elvis?

# Array comprehensions:
cubes = (math.cube num for num in list)
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;
})();
run: cubes

安裝

coffee 的命令列版本可用作 Node.js 工具程式。然而,核心編譯器 並不依賴於 Node,可以在任何 JavaScript 環境或瀏覽器中執行(請參閱 試用 CoffeeScript)。

要安裝,首先請確定您擁有 Node.js 最新穩定版本的有效副本。然後,您可以使用 npm 全域安裝 CoffeeScript

npm install --global coffeescript

這將使 coffeecake 命令可於全域使用。

當您需要 CoffeeScript 作為專案的相依項時,您可以在該專案的資料夾中進行本機安裝

npm install --save coffeescript

coffeecake 命令會先在目前資料夾中尋找 CoffeeScript 是否已在本機安裝,如果已安裝,則使用該版本。這允許在全域和本機安裝不同版本的 CoffeeScript。

用法

安裝後,您應該可以存取 coffee 命令,它可以執行腳本、將 .coffee 檔案編譯成 .js,並提供互動式 REPL。coffee 命令採用下列選項

選項 說明
-c, --compile .coffee 程式碼編譯成同名的 .js JavaScript 檔案。
-m, --map 在編譯的 JavaScript 檔案旁產生原始碼對應檔。也會將 sourceMappingURL 指令加入 JavaScript 中。
-M, --inline-map --map 相同,但將原始碼對應檔直接包含在編譯的 JavaScript 檔案中,而不是在獨立的檔案中。
-i, --interactive 啟動互動式 CoffeeScript 會話,以嘗試簡短的片段。與不帶參數呼叫 coffee 相同。
-o, --output [DIR] 將所有編譯的 JavaScript 檔案寫入指定的目錄中。搭配 --compile--watch 使用。
-w, --watch 監控檔案的變更,在任何檔案更新時重新執行指定的指令。
-p, --print 不將 JavaScript 寫入檔案,而是直接列印到 stdout
-s, --stdio 透過 STDIN 輸入 CoffeeScript,並透過 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,不使用 頂層函數安全性包裝器
-t, --tokens 僅對 CoffeeScript 進行詞法分析,而不進行解析,並列印出 token 串流。用於除錯編譯器。
-n, --nodes 僅對 CoffeeScript 進行詞法分析和解析,而不進行編譯,並列印出解析樹。用於除錯編譯器。
--nodejs node 可執行檔具有一些有用的選項,例如 --debug--debug-brk--max-stack-size--expose-gc。使用此標誌將選項直接傳遞至 Node.js。若要傳遞多個標誌,請多次使用 --nodejs
--no-header 抑制「由 CoffeeScript 生成」標頭。

範例

可讀的 CoffeeScript

除了作為一種普通的程式語言使用之外,CoffeeScript 也可以用「可讀」模式撰寫。如果您使用 .litcoffee 副檔名命名檔案,就可以將其寫成 Markdown 文件,而這個文件同時也是可執行的 CoffeeScript 程式碼。編譯器會將任何縮排區塊(Markdown 表示原始程式碼的方式)視為程式碼,並將其餘部分視為註解而忽略。

僅供參考,目前編譯器的一小部分是以這種方式實作的:請參閱 文件原始碼,以及 在文字編輯器中正確突顯的程式碼

語言參考

此參考文件採用由上而下的結構,方便您閱讀。後面的章節會使用前面介紹的概念和語法。假設您已熟悉 JavaScript。在以下所有範例中,CoffeeScript 原始碼會顯示在左側,而直接編譯成 JavaScript 的程式碼則會顯示在右側。

許多範例都可以執行(在有意義的情況下),方法是按一下右側的執行按鈕,並可透過按一下左側的載入按鈕載入「試用 CoffeeScript」主控台。

首先,基本知識:CoffeeScript 使用顯著空白來界定程式碼區塊。您不需要使用分號 ; 來終止表達式,結束該行就足夠了(儘管分號仍然可用於將多個表達式放入單一行中)。不要使用大括號 { } 來包圍 函式if 陳述式switchtry/catch 中的程式碼區塊,請使用縮排。

如果您傳遞引數,則不需要使用括號來呼叫函式。隱式呼叫會向前包覆到該行或區塊表達式的結尾。
console.log sys.inspect objectconsole.log(sys.inspect(object));

函式

函式由括號中的選用參數清單、箭頭和函式主體定義。空函式看起來像這樣:->

square = (x) -> x * x
cube   = (x) -> square(x) * x
var cube, square;

square = function(x) {
  return x * x;
};

cube = function(x) {
  return square(x) * x;
};
載入
執行:cube(5)

函式也可以為引數設定預設值,如果沒有傳入引數(nullundefined),則會使用預設值。

fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."
var fill;

fill = function(container, liquid) {
  if (liquid == null) {
    liquid = "coffee";
  }
  return "Filling the " + container + " with " + liquid + "...";
};
載入
執行:fill("cup")

物件和陣列

物件和陣列的 CoffeeScript 文字看起來與 JavaScript 的表親非常相似。當每個屬性列在自己的行中時,逗號是可選的。可以透過縮排建立物件,而不是使用明確的大括號,類似於 YAML

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
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
  }
};
載入
執行:song.join(" … ")

在 JavaScript 中,您不能使用保留字,例如 class,作為物件的屬性,而不將它們引用為字串。CoffeeScript 會注意到在物件中用作金鑰的保留字,並為您引用它們,因此您不必擔心(例如,在使用 jQuery 時)。

$('.account').attr class: 'active'

log object.class
$('.account').attr({
  "class": 'active'
});

log(object["class"]);
載入

當您希望將金鑰設定為同名變數時,CoffeeScript 有建立物件的捷徑。

name = "Michelangelo"
mask = "orange"
weapon = "nunchuks"
turtle = {name, mask, weapon}
output = "#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!"
var mask, name, output, turtle, weapon;

name = "Michelangelo";

mask = "orange";

weapon = "nunchuks";

turtle = {
  name: name,
  mask: mask,
  weapon: weapon
};

output = turtle.name + " wears an " + turtle.mask + " mask. Watch out for his " + turtle.weapon + "!";
載入

字彙範圍和變數安全性

CoffeeScript 編譯器會確保所有變數都適當地宣告於詞彙範圍內,您永遠不需要自己撰寫 var

outer = 1
changeNumbers = ->
  inner = -1
  outer = 10
inner = changeNumbers()
var changeNumbers, inner, outer;

outer = 1;

changeNumbers = function() {
  var inner;
  inner = -1;
  return outer = 10;
};

inner = changeNumbers();
載入
執行:內部

請注意,所有變數宣告都會向上推到最近的範圍頂端,在它們第一次出現時。outer 沒有在內部函式中重新宣告,因為它已經在範圍內;另一方面,函式內的 inner 不應該能夠變更同名的外部變數值,因此有它自己的宣告。

此行為實際上與 Ruby 的局部變數範圍相同。因為您無法直接存取 var 關鍵字,因此不可能故意遮蔽外部變數,您只能參照它。因此,如果您撰寫深度巢狀函式,請小心不要意外重複使用外部變數的名稱。

雖然為了清楚起見,在本文檔中已隱藏,但所有 CoffeeScript 輸出都包裝在一個匿名函式中:(function(){ … })(); 這個安全包裝器與 var 關鍵字的自動產生相結合,使得意外污染全域名稱空間變得極為困難。

如果您想為其他腳本建立頂層變數以供使用,請將它們附加為 window 上的屬性;將它們附加為 CommonJS 中 exports 物件上的屬性;或使用 export 陳述式。如果您同時鎖定 CommonJS 和瀏覽器,存在運算子(如下所述)提供了一個可靠的方法來找出在哪裡新增它們:exports ? this

如果、否則、除非和條件式指派

if/else 敘述可以不用括號和花括號來寫。和函式及其他區塊表達式一樣,多行條件式以縮排來區分。還有一個方便的後置形式,ifunless 在結尾。

CoffeeScript 可以將 if 敘述編譯成 JavaScript 表達式,可能的話使用三元運算子,否則使用封閉包裝。CoffeeScript 中沒有明確的三元敘述 — 你只要在單一行上使用一般的 if 敘述。

mood = greatlyImproved if singing

if happy and knowsIt
  clapsHands()
  chaChaCha()
else
  showIt()

date = if friday then sue else jill
var date, mood;

if (singing) {
  mood = greatlyImproved;
}

if (happy && knowsIt) {
  clapsHands();
  chaChaCha();
} else {
  showIt();
}

date = friday ? sue : jill;
載入

散列…

JavaScript arguments 物件 是處理接受可變數量引數函式的有用方式。CoffeeScript 提供散列 ...,用於函式定義和呼叫,讓可變數量引數變得更可口。

gold = silver = rest = "unknown"

awardMedals = (first, second, others...) ->
  gold   = first
  silver = second
  rest   = others

contenders = [
  "Michael Phelps"
  "Liu Xiang"
  "Yao Ming"
  "Allyson Felix"
  "Shawn Johnson"
  "Roman Sebrle"
  "Guo Jingjing"
  "Tyson Gay"
  "Asafa Powell"
  "Usain Bolt"
]

awardMedals contenders...

alert "Gold: " + gold
alert "Silver: " + silver
alert "The Field: " + rest
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);
載入
執行

迴圈和理解

你會在 CoffeeScript 中寫的大部分迴圈,會是陣列、物件和範圍上的 理解。理解取代(並編譯成)for 迴圈,加上可選的防護子句和目前陣列索引的值。和 for 迴圈不同的是,陣列理解是表達式,可以傳回和指定。

# Eat lunch.
eat food for food in ['toast', 'cheese', 'wine']

# Fine five course dining.
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
menu i + 1, dish for dish, i in courses

# Health conscious meal.
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'
var courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;

ref = ['toast', 'cheese', 'wine'];
for (j = 0, len = ref.length; j < len; j++) {
  food = ref[j];
  eat(food);
}

courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];

for (i = k = 0, len1 = courses.length; k < len1; i = ++k) {
  dish = courses[i];
  menu(i + 1, dish);
}

foods = ['broccoli', 'spinach', 'chocolate'];

for (l = 0, len2 = foods.length; l < len2; l++) {
  food = foods[l];
  if (food !== 'chocolate') {
    eat(food);
  }
}
載入

理解應該可以處理大部分你會使用迴圈、each/forEachmapselect/filter 的地方,例如
shortNames = (name for name in list when name.length < 5)
如果你知道迴圈的開始和結束,或想以固定大小增量逐步執行,你可以使用範圍來指定理解的開始和結束。

countdown = (num for num in [10..1])
var countdown, num;

countdown = (function() {
  var i, results;
  results = [];
  for (num = i = 10; i >= 1; num = --i) {
    results.push(num);
  }
  return results;
})();
載入
執行:倒數

請注意,由於我們在上面的範例中將理解的結果指派給變數,CoffeeScript 會將每次反覆運算的結果收集到陣列中。有時候函式會以僅打算執行其副作用的迴圈作結。小心不要在這些情況下意外傳回理解的結果,請在函式的底部加上有意義的傳回值,例如 truenull

若要以固定大小的區塊逐步執行範圍理解,請使用 by,例如:evens = (x for x in [0..10] by 2)

如果您不需要目前的反覆運算值,您可以省略它:browser.closeCurrentTab() for [0...count]

理解也可以用來反覆運算物件中的鍵和值。使用 of 來表示理解物件的屬性,而不是陣列中的值。

yearsOld = max: 10, ida: 9, tim: 11

ages = for child, age of yearsOld
  "#{child} is #{age}"
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;
})();
載入
執行:ages.join(", ")

如果您只想反覆運算物件本身定義的鍵,請加上 hasOwnProperty 檢查以避免繼承自原型屬性,請使用 for own key, value of object

若要反覆運算產生器函式,請使用 from。請參閱 產生器函式

CoffeeScript 提供的唯一低階迴圈是 while 迴圈。與 JavaScript 的主要不同點在於 while 迴圈可以用作表達式,傳回包含迴圈中每次反覆運算結果的陣列。

# Econ 101
if this.studyingEconomics
  buy()  while supply > demand
  sell() until supply > demand

# Nursery Rhyme
num = 6
lyrics = while num -= 1
  "#{num} little monkeys, jumping on the bed.
    One fell out and bumped his head."
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;
})();
載入
執行:lyrics.join("\n")

為了可讀性,until 關鍵字等於 while not,而 loop 關鍵字等於 while true

使用 JavaScript 迴圈產生函式時,通常會插入封閉包裝,以確保迴圈變數封閉,而所有產生的函式不會只共用最後的數值。CoffeeScript 提供 do 關鍵字,它會立即呼叫傳遞的函式,轉送任何引數。

for filename in list
  do (filename) ->
    fs.readFile filename, (err, contents) ->
      compile filename, contents.toString()
var filename, fn, i, len;

fn = function(filename) {
  return fs.readFile(filename, function(err, contents) {
    return compile(filename, contents.toString());
  });
};
for (i = 0, len = list.length; i < len; i++) {
  filename = list[i];
  fn(filename);
}
載入

使用範圍進行陣列切片和拼接

範圍也可以用來擷取陣列切片。使用兩個點 (3..6),範圍為包含式 (3, 4, 5, 6);使用三個點 (3...6),範圍會排除結尾 (3, 4, 5)。切片索引具有有用的預設值。省略的第一個索引預設為零,而省略的第二個索引預設為陣列大小。

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]

start   = numbers[0..2]

middle  = numbers[3...-2]

end     = numbers[-2..]

copy    = numbers[..]
var copy, end, middle, numbers, start;

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

start = numbers.slice(0, 3);

middle = numbers.slice(3, -2);

end = numbers.slice(-2);

copy = numbers.slice(0);
載入
執行:middle

相同的語法可以用於指定,以新的數值取代陣列的區段,並進行拼接。

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

numbers[3..6] = [-3, -4, -5, -6]
var numbers, ref;

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

[].splice.apply(numbers, [3, 4].concat(ref = [-3, -4, -5, -6])), ref;
載入
執行:numbers

請注意,JavaScript 字串是不可變的,且無法拼接。

一切都為表達式(至少盡可能)

您可能已經注意到,即使我們沒有在 CoffeeScript 函式中新增 return 陳述式,它們仍然會傳回最後的數值。CoffeeScript 編譯器會嘗試確保語言中的所有陳述式都能用作表達式。請注意,在以下函式中,return 如何被推入執行中的每個可能分支。

grade = (student) ->
  if student.excellentWork
    "A+"
  else if student.okayStuff
    if student.triedHard then "B" else "B-"
  else
    "C"

eldest = if 24 > 21 then "Liz" else "Ike"
var eldest, grade;

grade = function(student) {
  if (student.excellentWork) {
    return "A+";
  } else if (student.okayStuff) {
    if (student.triedHard) {
      return "B";
    } else {
      return "B-";
    }
  } else {
    return "C";
  }
};

eldest = 24 > 21 ? "Liz" : "Ike";
載入
執行:eldest

即使函式總是會傳回其最終值,但在你知道已完成時,可以且建議從函式主體中提早傳回,寫出明確的傳回(return value)。

因為變數宣告發生在範圍的頂端,所以指派可以用在表達式中,即使對於之前未曾見過的變數也是如此

six = (one = 1) + (two = 2) + (three = 3)
var one, six, three, two;

six = (one = 1) + (two = 2) + (three = 3);
載入
執行:six

在 CoffeeScript 中,當用於表達式的一部分時,在 JavaScript 中原本會是陳述式的事物,會透過將其包裝在封閉中而轉換成表達式。這讓你能夠執行有用的操作,例如將理解的結果指派給變數

# The first ten global properties.

globals = (name for name of window)[0...10]
var globals, name;

globals = ((function() {
  var results;
  results = [];
  for (name in window) {
    results.push(name);
  }
  return results;
})()).slice(0, 10);
載入
執行:globals

以及執行愚蠢的操作,例如將 try/catch 陳述式直接傳遞到函式呼叫中

alert(
  try
    nonexistent / undefined
  catch error
    "And the error is ... #{error}"
)
var error;

alert((function() {
  try {
    return nonexistent / void 0;
  } catch (error1) {
    error = error1;
    return "And the error is ... " + error;
  }
})());
載入
執行

在 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 物件金鑰的存在。

為了簡化數學表達式,** 可用於指數運算,而 // 執行整數除法。% 的作用就像在 JavaScript 中一樣,而 %% 提供 “除數相關模數運算”

-7 % 5 == -2 # The remainder of 7 / 5
-7 %% 5 == 3 # n %% 5 is always between 0 and 4

tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length)
var modulo = function(a, b) { return (+a % (b = +b) + b) % b; };

-7 % 5 === -2;

modulo(-7, 5) === 3;

tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length));
載入

現在全部一起

CoffeeScript JavaScript
is ===
isnt !==
!
&&
||
trueyeson
falsenooff
@this
無 JS 等效
a ** b Math.pow(a, b)
a // b Math.floor(a / b)
a %% b (a % b + b) % b
launch() if ignition is on

volume = 10 if band isnt SpinalTap

letTheWildRumpusBegin() unless answer is no

if car.speed < limit then accelerate()

winner = yes if pick in [47, 92, 13]

print inspect "My name is #{@name}"
var volume, winner;

if (ignition === true) {
  launch();
}

if (band !== SpinalTap) {
  volume = 10;
}

if (answer !== false) {
  letTheWildRumpusBegin();
}

if (car.speed < limit) {
  accelerate();
}

if (pick === 47 || pick === 92 || pick === 13) {
  winner = true;
}

print(inspect("My name is " + this.name));
載入

存在運算子

在 JavaScript 中,檢查變數是否存在有點困難。if (variable) … 接近,但對於零、空字串和 false 會失敗。CoffeeScript 的存在運算子 ? 會傳回 true,除非變數為 nullundefined,這使其類似於 Ruby 的 nil?

它也可以用於比 ||= 提供更安全的條件賦值,適用於可能處理數字或字串的情況。

solipsism = true if mind? and not world?

speed = 0
speed ?= 15

footprints = yeti ? "bear"
var footprints, solipsism, speed;

if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {
  solipsism = true;
}

speed = 0;

if (speed == null) {
  speed = 15;
}

footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
載入
執行:足跡

存在運算子的存取器變體 ?. 可用於吸收屬性鏈中的 null 參考。在基底值可能是 nullundefined 的情況下,使用它來取代點存取器 .。如果所有屬性都存在,則您將獲得預期的結果,如果鏈斷裂,則會傳回 undefined,而不是會引發的 TypeError

zip = lottery.drawWinner?().address?.zipcode
var ref, zip;

zip = typeof lottery.drawWinner === "function" ? (ref = lottery.drawWinner().address) != null ? ref.zipcode : void 0 : void 0;
載入

吸收 null 類似於 Ruby 的 andand gem,以及 Groovy 中的 安全導覽運算子

類別、繼承和 Super

JavaScript 的原型繼承一直有點令人費解,有一整套提供更簡潔語法,用於 JavaScript 原型上古典繼承的函式庫家族:Base2Prototype.jsJS.Class 等。這些函式庫提供語法糖,但內建繼承會完全可用,如果不是因為幾個小例外:呼叫 super(原型物件對目前函式的實作)很奇怪,而且正確設定原型鏈很奇怪。

CoffeeScript 提供一個基本的 class 結構,讓您可以命名類別、設定超類別、指定原型屬性,以及在單一可指定表達式中定義建構函式,而不是重複將函式附加到原型。

建構函式函式有命名,以更好地支援有用的堆疊追蹤。在以下範例的第一個類別中,this.constructor.name 是 "Animal"

class Animal
  constructor: (@name) ->

  move: (meters) ->
    alert @name + " moved #{meters}m."

class Snake extends Animal
  move: ->
    alert "Slithering..."
    super 5

class Horse extends Animal
  move: ->
    alert "Galloping..."
    super 45

sam = new Snake "Sammy the Python"
tom = new Horse "Tommy the Palomino"

sam.move()
tom.move()
var Animal, Horse, Snake, sam, tom,
  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  hasProp = {}.hasOwnProperty;

Animal = (function() {
  function Animal(name) {
    this.name = name;
  }

  Animal.prototype.move = function(meters) {
    return alert(this.name + (" moved " + meters + "m."));
  };

  return Animal;

})();

Snake = (function(superClass) {
  extend(Snake, superClass);

  function Snake() {
    return Snake.__super__.constructor.apply(this, arguments);
  }

  Snake.prototype.move = function() {
    alert("Slithering...");
    return Snake.__super__.move.call(this, 5);
  };

  return Snake;

})(Animal);

Horse = (function(superClass) {
  extend(Horse, superClass);

  function Horse() {
    return Horse.__super__.constructor.apply(this, arguments);
  }

  Horse.prototype.move = function() {
    alert("Galloping...");
    return Horse.__super__.move.call(this, 45);
  };

  return Horse;

})(Animal);

sam = new Snake("Sammy the Python");

tom = new Horse("Tommy the Palomino");

sam.move();

tom.move();
載入
執行

如果用傳統的方式建立原型不是你的菜,CoffeeScript 提供了幾個較低層級的便利功能。extends 運算子有助於適當的原型設定,可用於在任何一對建構函數之間建立繼承鏈;:: 讓你快速存取物件的原型;而 super() 會轉換成呼叫同名的直接祖先方法。

String::dasherize = ->
  this.replace /_/g, "-"
String.prototype.dasherize = function() {
  return this.replace(/_/g, "-");
};
載入
執行:「one_two」。dasherize()

最後,類別定義是可執行程式碼區塊,這會產生有趣的元程式設計可能性。因為在類別定義的脈絡中,this 是類別物件本身(建構函數),你可以使用 @property: value 指定靜態屬性,並呼叫在父類別中定義的函數:@attr 'title', type: 'text'

解構賦值

就像 JavaScript(自 ES2015 以來),CoffeeScript 有解構賦值語法。當你將陣列或物件文字指定給值時,CoffeeScript 會將兩邊分解並相互比對,將右邊的值指定給左邊的變數。在最簡單的情況下,它可用於平行賦值

theBait   = 1000
theSwitch = 0

[theBait, theSwitch] = [theSwitch, theBait]
var ref, theBait, theSwitch;

theBait = 1000;

theSwitch = 0;

ref = [theSwitch, theBait], theBait = ref[0], theSwitch = ref[1];
載入
執行:theBait

但它也有助於處理會傳回多個值的函數。

weatherReport = (location) ->
  # Make an Ajax request to fetch the weather...
  [location, 72, "Mostly Sunny"]

[city, temp, forecast] = weatherReport "Berkeley, CA"
var city, forecast, ref, temp, weatherReport;

weatherReport = function(location) {
  return [location, 72, "Mostly Sunny"];
};

ref = weatherReport("Berkeley, CA"), city = ref[0], temp = ref[1], forecast = ref[2];
載入
執行:forecast

解構賦值可用於任何深度陣列和物件巢狀結構,以協助取出深度巢狀屬性。

futurists =
  sculptor: "Umberto Boccioni"
  painter:  "Vladimir Burliuk"
  poet:
    name:   "F.T. Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]

{sculptor} = futurists

{poet: {name, address: [street, city]}} = futurists
var city, futurists, name, ref, ref1, sculptor, street;

futurists = {
  sculptor: "Umberto Boccioni",
  painter: "Vladimir Burliuk",
  poet: {
    name: "F.T. Marinetti",
    address: ["Via Roma 42R", "Bellagio, Italy 22021"]
  }
};

sculptor = futurists.sculptor;

ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[0], city = ref1[1]);
載入
執行:name + "-" + street

解構賦值甚至可以與展開結合使用。

tag = "<impossible>"

[open, contents..., close] = tag.split("")
var close, contents, i, open, ref, tag,
  slice = [].slice;

tag = "<impossible>";

ref = tag.split(""), open = ref[0], contents = 3 <= ref.length ? slice.call(ref, 1, i = ref.length - 1) : (i = 1, []), close = ref[i++];
載入
執行:contents.join("")

展開可用於從陣列的尾端擷取元素,而不需要指定其餘的值。它也適用於函式參數清單。

text = "Every literary critic believes he will
        outwit history and have the last word"

[first, ..., last] = text.split " "
var first, last, ref, text;

text = "Every literary critic believes he will outwit history and have the last word";

ref = text.split(" "), first = ref[0], last = ref[ref.length - 1];
載入
執行:first + " " + last

解構賦值與類別建構函式結合使用時也很有用,可將屬性從傳遞給建構函式的選項物件指定給您的執行個體。

class Person
  constructor: (options) ->
    {@name, @age, @height = 'average'} = options

tim = new Person name: 'Tim', age: 4
var Person, tim;

Person = (function() {
  function Person(options) {
    var ref;
    this.name = options.name, this.age = options.age, this.height = (ref = options.height) != null ? ref : 'average';
  }

  return Person;

})();

tim = new Person({
  name: 'Tim',
  age: 4
});
載入
執行:tim.age + " " + tim.height

上述範例也示範了,如果解構物件或陣列中缺少屬性,您可以像在 JavaScript 中一樣提供預設值。與 JavaScript 的不同之處在於,CoffeeScript 一如往常地將 null 和 undefined 視為相同。

繫結函式、產生器函式

在 JavaScript 中,this 關鍵字會動態範圍化,表示當前函式附加到的物件。如果您將函式傳遞為回呼或附加到不同的物件,this 的原始值將會遺失。如果您不熟悉此行為,這篇 Digital Web 文章 對這些怪癖提供了良好的概觀。

可以使用粗體箭頭 => 來定義函式,並將其繫結到 this 的目前值,就在現場。這在使用基於回呼的函式庫(例如 Prototype 或 jQuery)時很有用,用於建立要傳遞給 each 的反覆運算函式,或與 on 一起使用的事件處理函式。使用粗體箭頭建立的函式能夠存取其定義所在 this 的屬性。

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').on 'click', (event) =>
    @customer.purchase @cart
var Account;

Account = function(customer, cart) {
  this.customer = customer;
  this.cart = cart;
  return $('.shopping_cart').on('click', (function(_this) {
    return function(event) {
      return _this.customer.purchase(_this.cart);
    };
  })(this));
};
載入

如果我們在上面的回呼中使用 ->@customer 會參照 DOM 元素未定義的「customer」屬性,並嘗試在其上呼叫 purchase() 會引發例外狀況。

在類別定義中使用時,使用粗體箭頭宣告的方法會在建立實例時自動繫結到類別的每個實例。

CoffeeScript 函式也支援 ES2015 產生器函式,透過 yield 關鍵字。沒有 function*(){} 這種無稽之談,CoffeeScript 中的產生器只是一個會產生結果的函式。

perfectSquares = ->
  num = 0
  loop
    num += 1
    yield num * num
  return

window.ps or= perfectSquares()
var perfectSquares;

perfectSquares = function*() {
  var num;
  num = 0;
  while (true) {
    num += 1;
    yield num * num;
  }
};

window.ps || (window.ps = perfectSquares());
載入
執行:ps.next().value

yield* 稱為 yield from,如果需要強制產生器不產生結果,可以使用 yield return

你可以使用 for…from 來迭代生成器函式。

fibonacci = ->
  [previous, current] = [1, 1]
  loop
    [previous, current] = [current, previous + current]
    yield current
  return

getFibonacciNumbers = (length) ->
  results = [1]
  for n from fibonacci()
    results.push n
    break if results.length is length
  results
var fibonacci, getFibonacciNumbers;

fibonacci = function*() {
  var current, previous, ref, ref1;
  ref = [1, 1], previous = ref[0], current = ref[1];
  while (true) {
    ref1 = [current, previous + current], previous = ref1[0], current = ref1[1];
    yield current;
  }
};

getFibonacciNumbers = function(length) {
  var n, ref, results;
  results = [1];
  ref = fibonacci();
  for (n of ref) {
    results.push(n);
    if (results.length === length) {
      break;
    }
  }
  return results;
};
載入
執行:getFibonacciNumbers(10)

內嵌 JavaScript

希望你永遠不需要使用它,但如果你需要在 CoffeeScript 中穿插 JavaScript 片段,你可以使用反引號直接傳遞。

hi = `function() {
  return [document.title, "Hello JavaScript"].join(": ");
}`
var hi;

hi = function() {
  return [document.title, "Hello JavaScript"].join(": ");
};
載入
執行:hi()

使用反斜線來跳脫反引號:\`​ 變成 `​

使用更多反斜線來跳脫反引號前的反斜線:\\\`​ 變成 \`​

markdown = `function () {
  return \`In Markdown, write code like \\\`this\\\`\`;
}`
var markdown;

markdown = function () {
  return `In Markdown, write code like \`this\``;
};
載入
執行:markdown()

你也可以使用三個反引號來內嵌 JavaScript 程式區塊。如果你需要在 JavaScript 程式區塊中使用反引號,這比跳脫反引號容易。

```
function time() {
  return `The time is ${new Date().toLocaleTimeString()}`;
}
```

function time() {
  return `The time is ${new Date().toLocaleTimeString()}`;
}
;

載入
執行:time()

Switch/When/Else

JavaScript 中的 Switch 陳述式有點奇怪。你需要記得在每個 case 陳述式的結尾處 break,以避免意外地落入預設情況。CoffeeScript 會防止意外落入,並且可以將 switch 轉換為可傳回、可指派的表達式。格式為:switch 條件,when 子句,else 預設情況。

與 Ruby 一樣,CoffeeScript 中的 switch 陳述式可以為每個 when 子句採用多個值。如果任何值相符,該子句就會執行。

switch day
  when "Mon" then go work
  when "Tue" then go relax
  when "Thu" then go iceFishing
  when "Fri", "Sat"
    if day is bingoDay
      go bingo
      go dancing
  when "Sun" then go church
  else go work
switch (day) {
  case "Mon":
    go(work);
    break;
  case "Tue":
    go(relax);
    break;
  case "Thu":
    go(iceFishing);
    break;
  case "Fri":
  case "Sat":
    if (day === bingoDay) {
      go(bingo);
      go(dancing);
    }
    break;
  case "Sun":
    go(church);
    break;
  default:
    go(work);
}
載入

Switch 陳述式也可以在沒有控制表達式的狀況下使用,將它們變成 if/else 鏈的更簡潔替代方案。

score = 76
grade = switch
  when score < 60 then 'F'
  when score < 70 then 'D'
  when score < 80 then 'C'
  when score < 90 then 'B'
  else 'A'
# grade == 'C'
var grade, score;

score = 76;

grade = (function() {
  switch (false) {
    case !(score < 60):
      return 'F';
    case !(score < 70):
      return 'D';
    case !(score < 80):
      return 'C';
    case !(score < 90):
      return 'B';
    default:
      return 'A';
  }
})();
載入

Try/Catch/Finally

Try 表達式具有與 JavaScript 中 try 陳述式相同的語意,儘管在 CoffeeScript 中,你可以省略 catchfinally 部分。如果不需要,catch 部分也可以省略錯誤參數。

try
  allHellBreaksLoose()
  catsAndDogsLivingTogether()
catch error
  print error
finally
  cleanUp()
var error;

try {
  allHellBreaksLoose();
  catsAndDogsLivingTogether();
} catch (error1) {
  error = error1;
  print(error);
} finally {
  cleanUp();
}
載入

鏈式比較

CoffeeScript 借用 Python 的鏈式比較,讓測試值是否落在特定範圍內變得容易。

cholesterol = 127

healthy = 200 > cholesterol > 60
var cholesterol, healthy;

cholesterol = 127;

healthy = (200 > cholesterol && cholesterol > 60);
載入
執行:healthy

字串內插、區塊字串和區塊註解

CoffeeScript 包含 Ruby 風格的字串內插。雙引號字串允許內插值,使用 #{ … },而單引號字串是字面意思。你甚至可以在物件鍵中使用內插。

author = "Wittgenstein"
quote  = "A picture is a fact. -- #{ author }"

sentence = "#{ 22 / 7 } is a decent approximation of π"
var author, quote, sentence;

author = "Wittgenstein";

quote = "A picture is a fact. -- " + author;

sentence = (22 / 7) + " is a decent approximation of π";
載入
執行:sentence

CoffeeScript 允許多行字串。除非以反斜線結尾,否則行會以單一空格連接。縮排會被忽略。

mobyDick = "Call me Ishmael. Some years ago --
  never mind how long precisely -- having little
  or no money in my purse, and nothing particular
  to interest me on shore, I thought I would sail
  about a little and see the watery part of the
  world..."
var mobyDick;

mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
載入
執行:mobyDick

區塊字串可用於容納格式化或對縮排敏感的文字(或者,如果你只是不想跳脫引號和撇號)。開始區塊的縮排層級會在整個區塊中維持,因此你可以讓它與程式碼主體保持對齊。

html = """
       <strong>
         cup of coffeescript
       </strong>
       """
var html;

html = "<strong>\n  cup of coffeescript\n</strong>";
載入
執行:html

雙引號區塊字串,就像其他雙引號字串一樣,允許內插。

有時你會希望將區塊註解傳遞到產生的 JavaScript 中。例如,當你需要在檔案頂端嵌入授權標頭時。區塊註解,它反映區塊字串的語法,會保留在產生的程式碼中。

###
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
###

/*
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
 */

載入

標記範本字串

CoffeeScript 支援 ES2015 標記範本字串,這能讓使用者自訂字串內插。如果你在字串前面加上一個函式名稱(中間沒有空格),CoffeeScript 會將這個「函式加字串」組合輸出為 ES2015 標記範本字串,這會 產生相應的行為:呼叫函式,其中參數為輸入文字和組成內插字串的表達式部分。然後,函式可以將這些部分組裝成輸出字串,提供自訂字串內插。

請注意,CoffeeScript 編譯器會為這個功能輸出 ES2015 語法,因此你的目標 JavaScript 執行環境必須支援這個語法才能讓你的程式碼運作;或者,你可以使用像 BabelTraceur Compiler 的工具將這個 ES2015 語法轉換成相容的 JavaScript。

upperCaseExpr = (textParts, expressions...) ->
  textParts.reduce (text, textPart, i) ->
    text + expressions[i - 1].toUpperCase() + textPart

greet = (name, adjective) ->
  upperCaseExpr"""
               Hi #{name}. You look #{adjective}!
               """
var greet, upperCaseExpr,
  slice = [].slice;

upperCaseExpr = function() {
  var expressions, textParts;
  textParts = arguments[0], expressions = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  return textParts.reduce(function(text, textPart, i) {
    return text + expressions[i - 1].toUpperCase() + textPart;
  });
};

greet = function(name, adjective) {
  return upperCaseExpr`Hi ${name}. You look ${adjective}!`;
};
載入
執行:greet("greg", "awesome")

區塊正規表示式

類似於區塊字串和註解,CoffeeScript 支援區塊正規表示式 — 忽略內部空白字元且可以包含註解和內插的延伸正規表示式。CoffeeScript 的區塊正規表示式仿效 Perl 的 /x 修飾詞,以 /// 為分隔符號,有助於讓複雜的正規表示式變得更易於閱讀。引用 CoffeeScript 原始碼

OPERATOR = /// ^ (
  ?: [-=]>             # function
   | [-+*/%<>&|^!?=]=  # compound assign / compare
   | >>>=?             # zero-fill right shift
   | ([-+:])\1         # doubles
   | ([&|<>])\2=?      # logic / shift
   | \?\.              # soak access
   | \.{2,3}           # range or splat
) ///
var OPERATOR;

OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
載入

模組

CoffeeScript 支援 ES2015 模組,其 importexport 語法非常類似

import 'local-file.coffee'
import 'coffeescript'

import _ from 'underscore'
import * as underscore from 'underscore'

import { now } from 'underscore'
import { now as currentTimestamp } from 'underscore'
import { first, last } from 'underscore'
import utilityBelt, { each } from 'underscore'

export default Math
export square = (x) -> x * x
export class Mathematics
  least: (x, y) -> if x < y then x else y

export { sqrt }
export { sqrt as squareRoot }
export { Mathematics as default, sqrt as squareRoot }

export * from 'underscore'
export { max, min } from 'underscore'
import 'local-file.coffee';

import 'coffeescript';

import _ from 'underscore';

import * as underscore from 'underscore';

import {
  now
} from 'underscore';

import {
  now as currentTimestamp
} from 'underscore';

import {
  first,
  last
} from 'underscore';

import utilityBelt, {
  each
} from 'underscore';

export default Math;

export var square = function(x) {
  return x * x;
};

export var Mathematics = (function() {
  function Mathematics() {}

  Mathematics.prototype.least = function(x, y) {
    if (x < y) {
      return x;
    } else {
      return y;
    }
  };

  return Mathematics;

})();

export {
  sqrt
};

export {
  sqrt as squareRoot
};

export {
  Mathematics as default,
  sqrt as squareRoot
};

export * from 'underscore';

export {
  max,
  min
} from 'underscore';
載入

請注意,CoffeeScript 編譯器不會解析模組;在 CoffeeScript 中撰寫 importexport 陳述式會在結果輸出中產生 importexport 陳述式。您有責任附加另一個轉譯器,例如 Traceur CompilerBabelRollup,以將此 ES2015 語法轉換為可在您的目標執行時期運作的程式碼。

另外請注意,任何含有 importexport 陳述式的檔案都將在沒有 頂層函式安全包裝器 的情況下輸出;換句話說,匯入或匯出模組會自動觸發該檔案的 bare 模式。這是因為根據 ES2015 規範,importexport 陳述式必須出現在最頂層範圍。

Cake 和 Cakefile

CoffeeScript 包含一個(非常)簡單的建置系統,類似於 MakeRake。它當然稱為 Cake,並用於建置和測試 CoffeeScript 語言本身的任務。任務定義在一個名為 Cakefile 的檔案中,並可透過在目錄內執行 cake [task] 來呼叫。若要列印所有任務和選項的清單,只需輸入 cake 即可。

任務定義是用 CoffeeScript 編寫的,因此您可以在 Cakefile 中放入任意程式碼。使用名稱、長描述和任務執行時要呼叫的函式來定義任務。如果您的任務採用命令列選項,您可以使用簡短和長旗標來定義選項,它將在 options 物件中提供。以下是使用 Node.js API 來重建 CoffeeScript 剖析器的任務

fs = require 'fs'

option '-o', '--output [DIR]', 'directory for compiled code'

task 'build:parser', 'rebuild the Jison parser', (options) ->
  require 'jison'
  code = require('./lib/grammar').parser.generate()
  dir  = options.output or 'lib'
  fs.writeFile "#{dir}/parser.js", code
var fs;

fs = require('fs');

option('-o', '--output [DIR]', 'directory for compiled code');

task('build:parser', 'rebuild the Jison parser', function(options) {
  var code, dir;
  require('jison');
  code = require('./lib/grammar').parser.generate();
  dir = options.output || 'lib';
  return fs.writeFile(dir + "/parser.js", code);
});
載入

如果您需要在另一個任務之前呼叫一個任務,例如在 test 之前執行 build,您可以使用 invoke 函式:invoke 'build'。Cake 任務是一種最小的方式,用於將您的 CoffeeScript 函式顯示在命令列上,因此 不要期待任何內建的奇特功能。如果您需要相依關係或非同步回呼,最好將它們放在您的程式碼本身中,而不是 Cake 任務中。

原始碼對應表

CoffeeScript 1.6.1 以上版本包含產生原始碼對應表的支援,這是一種告訴您的 JavaScript 引擎,您的 CoffeeScript 程式中哪一部分與正在評估的程式碼相符的方式。支援它的瀏覽器可以自動使用原始碼對應表在偵錯器中顯示您的原始原始碼。要在 JavaScript 檔案旁邊產生原始碼對應表,請將 --map-m 旗標傳遞給編譯器。

如需了解原始碼對應表的完整介紹、它們如何運作以及如何在您的瀏覽器中連結它們,請閱讀 HTML5 教學

「text/coffeescript」指令碼標籤

雖然不建議用於嚴肅用途,但可以使用 <script type="text/coffeescript"> 標籤直接在瀏覽器中包含 CoffeeScript。來源包含編譯器的壓縮和縮小版本(在此處下載當前版本,gzip 壓縮後為 51k),作為 docs/v1/browser-compiler/coffee-script.js。在包含內嵌 CoffeeScript 標籤的頁面上包含此檔案,它將依序編譯和評估這些標籤。

事實上,執行上方「試用 CoffeeScript」的少量膠水腳本,以及選單的 jQuery,就是以這種方式實作的。檢視來源並查看頁面底部以查看範例。包含腳本也會讓您可以存取 CoffeeScript.compile(),因此您可以開啟 Firebug 並嘗試編譯一些字串。

CoffeeScript 適用於一般警告 — 您的內嵌腳本將在封閉包裝中執行,因此如果您想要公開全域變數或函式,請將它們附加到 window 物件。

書籍

有許多優良的資源可以協助您開始使用 CoffeeScript,其中一些可以在線上免費取得。

螢幕錄製

範例

可以在 GitHub 上找到 最佳開源 CoffeeScript 範例清單。但再列舉幾個

資源

網路聊天(IRC)

通常可以在 CoffeeScript IRC 室中找到快速協助和建議。加入 irc.freenode.net 上的 #coffeescript,或按一下下方的按鈕,開啟此頁面上的網路聊天對話。

變更記錄

1.12.7

1.12.6

1.12.5

1.12.4

1.12.3

1.12.2

1.12.1

1.12.0

1.11.1

1.11.0

1.10.0

1.9.3

1.9.2

1.9.1

1.9.0

1.8.0

1.7.1

1.7.0

$ 'body'
.click (e) ->
  $ '.box'
  .fadeIn 'fast'
  .addClass '.active'
.css 'background', 'white'
$('body').click(function(e) {
  return $('.box').fadeIn('fast').addClass('.active');
}).css('background', 'white');
載入

1.6.3

1.6.2

1.6.1

1.5.0

1.4.0

1.3.3

1.3.1

1.2.0

1.1.3

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 中。splatted 參數宣告為函式的區域變數。

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 的第一個候選版本。自前一個版本以來,已進行大量內部變更,其中許多是從 satyr 的 CoffeeScript 方言 Coco 中貢獻的。已新增 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 現在使用適當命名的暫時變數,並在使用後回收其參照。已新增 require.extensions 支援 Node.js 0.3。現在在瀏覽器中載入 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 指令。新增一個自訂 jsl.conf 檔案,供我們偏好的 JavaScriptLint 設定使用。透過將運算規則扁平化,加快了 Jison 語法編譯時間。現在可以使用 JavaScript-minifier 友善語法來使用區塊註解。新增 JavaScript 的複合賦值位元運算子。修正了隱式物件文字的錯誤,這些文字具有數字和字串開頭鍵,作為隱式呼叫的主題,以及作為複合賦值的一部分。

0.9.1

0.9.1 的錯誤修正版本。大幅改善了混合隱式物件、隱式函式呼叫和隱式縮排的處理。字串和正規表示式內插現在嚴格為 #{ … }(Ruby 風格)。編譯器現在會採用 --require 旗標,它會指定在編譯前執行的指令碼。

0.9.0

The CoffeeScript 0.9 series is considered to be a release candidate for 1.0; let’s give her a shakedown cruise. 0.9.0 introduces a massive backwards-incompatible change: Assignment now uses =, and object literals use :, as in JavaScript. This allows us to have implicit object literals, and YAML-style object definitions. Half assignments are removed, in favor of +=, or=, and friends. Interpolation now uses a hash mark # instead of the dollar sign $ — because dollar signs may be part of a valid JS identifier. Downwards range comprehensions are now safe again, and are optimized to straight for loops when created with integer endpoints. A fast, unguarded form of object comprehension was added: for all key, value of object. Mentioning the super keyword with no arguments now forwards all arguments passed to the function, as in Ruby. If you extend class B from parent class A, if A has an extended method defined, it will be called, passing in B — this enables static inheritance, among other things. Cleaner output for functions bound with the fat arrow. @variables can now be used in parameter lists, with the parameter being automatically set as a property on the object — useful in constructors and setter functions. Constructor functions can now take splats.

0.7.2

快速修正錯誤(緊接在 0.7.1 之後),解決在某些情況下無法解析 coffee 命令列選項的問題。

0.7.1

區塊式註解現在會傳遞並列印為 JavaScript 區塊註解,使其可應用於授權條款和版權標題。透過 hashbangs 改善執行獨立咖啡腳本的支援。改善語法中不存在的記號的語法錯誤。

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 的 here 文件。現在支援 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

插值現在可以在正規表示式、heredoc 和字串中使用。增加了 <- 繫結運算子。允許指派給半表達式,而不是特殊的 ||= 類型的運算子。引數物件不再自動轉換成陣列。在需要 coffee-script 之後,Node.js 現在可以透過 registerExtension 直接載入 .coffee 檔案。現在可以在函式呼叫、陣列和模式配對中使用多個展開運算子。

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)都在使用它們。Cakefile 可以使用 optparse.coffee 來定義任務的選項。--run 現在是 coffee 指令的預設旗標,使用 --compile 來儲存 JavaScript。修正了正規表示式字面和鏈式除法之間的歧義。

0.5.2

加入了壓縮版的編譯器,以 browser-compiler/coffee-script.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,請傳遞 --narwhal 旗標。

0.3.0

CoffeeScript 0.3 包含重大的語法變更:函數符號已變更為 ->,而繫結函數符號現在是 =>。函數定義中的參數清單現在必須用括號括起來。新增了屬性浸潤,使用 ?. 算子。在呼叫帶有參數的函數時,括號變為可選。移除了過時的區塊文字語法。

0.2.6

新增了 Python 風格的鏈式比較、條件存在算子 ?=,以及一些來自《Beautiful Code》的範例。修正了與陳述式轉換為表達式、參數轉換為陣列,以及 TextMate 語法高亮顯示器相關的錯誤。

0.2.5

switch 陳述式中的條件現在可以一次取用多個值 — 如果其中任何一個為真,則會執行案例。新增長箭號 ==>,用於定義並立即將函式繫結到 this。while 迴圈現在可用作表達式,就像理解一樣。可以在模式比對中使用展開運算子來吸收陣列的其餘部分。

0.2.4

新增 ECMAScript Harmony 風格的解構賦值,用於處理從巢狀陣列和物件中擷取值。新增對縮排敏感的 here 文件,用於格式化良好的字串或程式碼區塊。

0.2.3

取消不令人滿意的 ino 關鍵字,並以 of 取代,用於物件理解。它們現在看起來像:for prop, value of object

0.2.2

在對物件執行理解時,請使用 ino,而不是 in,這有助於我們在編譯時產生更小、更有效的程式碼。新增 :: 作為表示 .prototype. 的簡寫。將「展開」符號從前置星號 * 變更為後置省略號 ...。新增 JavaScript 的 in 運算子、空的 return 陳述式和空的 while 迴圈。現在,以大寫字母開頭的建構函式會包含安全檢查,以確保傳回物件的新執行個體。extends 關鍵字現在的功能與 Google Closure Library 中的 goog.inherits 相同。

0.2.1

參數物件現在在被參照時會轉換成真正的陣列。

0.2.0

重大版本。顯著的空白。更好的陳述式轉換為表達式。Splat。Splice 文字。物件理解。區塊。存在運算子。非常感謝所有張貼問題的人,特別感謝 Liam O’Connor-Davis 的空白和表達式協助。

0.1.6

修正從 CoffeeScript 目錄之外執行 coffee --interactive--run 的錯誤。修正巢狀函式/if 陳述式的錯誤。

0.1.5

陣列切片文字和陣列理解現在都可以使用 Ruby 風格的範圍來指定開始和結束。JavaScript 變數宣告現在會推送到範圍的頂端,讓所有指定陳述式都變成表達式。您可以使用 \ 來跳脫換行。coffee-script 指令現在稱為 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 發行。