Adrian Liaw

CoffeeScript 是什麼??

CoffeeScript is a little language that compiles into JavaScript.

CoffeeScript 是一個可以轉換成JavaScript的小型語言

認識CoffeeScript的作者

Jeremy Ashkenas

Jeremy Ashkenas

  • 紐約時報圖形部門
  • Backbone.js 作者
  • Underscore.js 作者
  • CoffeeScript 作者

進入正題

CoffeeScript 的原則

It's just JavaScript

  • 它就只是JavaScript
  • 編譯器將CoffeeScript的程式一對一的轉換成JavaScript
  • 沒有所謂的"直譯器(interpreter)"
  • 你可以使用任何現有的JavaScript函式庫
  • 編譯出來的JavaScript是可讀性高的
  • 產生出的JavaScript有時比手寫的執行效率還高

為什麼要使用CoffeeScript

Why CoffeeScript

  • 程式碼很乾淨
  • 可以省掉一半的程式碼
  • 程式碼好讀,比較接近自然語言
  • 語法似Python, Ruby, Haskell
  • 人的時間貴於機器的時間

實務上來看

  • 使用縮排區分程式區塊
  • 省略不必要的括弧和分號
  • 增加了"class"語法 (OOP)
  • list comprehension (串列綜合運算)
  • 自動處理區域變數問題

而JavaScript...

  • 用大括弧來區分,到處都是大括弧
  • 一大堆有的沒的大括弧中括弧小括弧和分號
  • 一個是定義function,而另一個是定義function
  • 先產生一個空白的Array,然後用for loop一個個加
  • 定義變數用var不用var傻傻分不清楚

相信大家還是聽不懂

還是動手做比較快

Variables

myNumber = 10
myBool   = true
myString = "Hello World"
var myBool, myNumber, myString;

myNumber = 10;

myBool = true;

myString = "Hello World";

Function Calls

console.log "Hello"

Math.pow 2, 3

myDiv = $ "#my-div"
var myDiv;

console.log("Hello");

Math.pow(2, 3);

myDiv = $("#my-div");

Functions

square        = (x)    -> x * x
double_double = (x, y) -> (x + y) * 2

helloWorld = ->
  message = "Hello World"
  console.log message
var double_double, helloWorld, square;

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

double_double = function(x, y) {
  return (x + y) * 2;
};

helloWorld = function() {
  var message;
  message = "Hello World";
  return console.log(message);
};

Conditions

if a < b
  unless c is b
    if c isnt d
      console.log "FOO"
    else
      console.log "BAR"
if (a < b) {
  if (c !== b) {
    if (c !== d) {
      console.log("FOO");
    } else {
      console.log("BAR");
    }
  }
}

Comments

# This is a "line comment"

###
This is a "block comment"
###

/*
This is a "block comment"
 */

小練習1: 費氏數列

Fibonacci Time!

小練習1: 費式數列的第n項

fib(n) = fib(n-1) + fib(n - 2)
fib(n)=fib(n1)+fib(n2)
fib (0) = 1, fib(1) = 1
fib(0)=1,fib(1)=1
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...]

結果應該要長這樣

coffee> fib 5
8
coffee> fib 10
89
coffee> fib 0
1
coffee> fib 16
1597

String Formatting

n = 11
m = 3

console.log "#{n} powered by #{m} is #{Math.pow n, m}"
var m, n;

n = 11;

m = 3;

console.log(n + " powered by " + m + " is " + (Math.pow(n, m)));

Multiline Strings

agileManifesto = 
"""
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
"""
var agileManifesto;

agileManifesto = "Individuals and interactions over processes and tools\nWorking software over comprehensive documentation\nCustomer collaboration over contract negotiation\nResponding to change over following a plan";

Arrays

myList = [1, 2, 3, 4]

coders = [
  "Adrian Liaw"
  "Michael Pan"
  "Jeffrey Lee"
]
var coders, myList;

myList = [1, 2, 3, 4];

coders = ["Adrian Liaw", "Michael Pan", "Jeffrey Lee"];

Slices / Ranges

numbers = [1..10]

start = numbers[..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, 10];

start = numbers.slice(0, 3);

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

end = numbers.slice(-2);

copy = numbers.slice(0);

Objects

adrianliaw =
  name: "Adrian Liaw"
  age:  14
  sex:  "Male"
  
  
var adrianliaw;

adrianliaw = {
  name: "Adrian Liaw",
  age: 14,
  sex: "Male"
};

While Loops

while true
  console.log "Infinity Loop!"

until false
  console.log "Infinity Loop!"

buy thing while supply > demand

eat food until full
while (true) {
  console.log("Infinity Loop!");
}

while (!false) {
  console.log("Infinity Loop!");
}

while (supply > demand) {
  buy(thing);
}

while (!full) {
  eat(food);
}

For Loops

lunch = ["beef", "pasta", "apple"]

for food in lunch
  eat food
  console.log "Finished #{food}"

myObj =
  one: 1
  two: 2
  three: 3

for num, i of myObj
  console.log num, i
var food, i, lunch, myObj, num, _i, _len;


lunch = ["beef", "pasta", "apple"];

for (_i = 0, _len = lunch.length; _i < _len; _i++) {
  food = lunch[_i];
  eat(food);
  console.log("Finished " + food);
}

myObj = {
  one: 1,
  two: 2,
  three: 3
};

for (num in myObj) {
  i = myObj[num];
  console.log(num, i);
}

Extra Operators

CoffeeScript JavaScript
is
===
isnt
!==
not
!
and
&&
or
||
true, yes, on
true
false, no, off
off
CoffeeScript JavaScript
@, this
this
of
in
in
No JS equivalent
a ** b
Math.pow(a, b)
a // b
Math.floor(a / b)
a %% b
(a % b + b) % b

小練習2: 重複字串

Repeating String

在Python裡面,我們如果要反覆一個字串,可以這樣:

>>> "string" * 3

但在JavaScript裡做這樣的動作只會回傳NaN

用CoffeeScript寫一個吧!

Repeating String

定義一個function,有兩個參數,第一個是字串s,第二個是數字n,回傳s重覆n次的字串

coffee> repeat "hello", 3
'hellohellohello'

coffee> repeat "Kids Coding Studio!", 2
'Kids Coding Studio!Kids Coding Studio!'

coffee> repeat "Michael", 1
'Michael'

coffee> repeat "FooBarBaz", 0
''

小練習3: 金字塔

Pyramid

印出x層的金字塔!

coffee> pyramid 5
    *
   ***
  *****
 *******
*********
coffee> pyramid 8
       *
      ***
     *****
    *******
   *********
  ***********
 *************
***************

Array Comprehensions

什麼是Array Comprehension??

在Python裡叫"List Comprehension"

它來自數學的"Set Comprehension"

映射輸出值

變數

輸入值集合

條件

其實就等於

inputSet = [0..10]
outputSet = []
for x in inputSet
  if x ** 2 > 3
    ouputSet.push 2 * x

用Array Comprehension 來簡化

output = (2 * x for x in [0..10] when x ** 2 > 3)
output = (
  2 * x \             # 映射值
  for x in [0..10] \ # 輸入值集合
  when x ** 2 > 3     # 條件
)
output = (2 * x for x in [0..10] when x ** 2 > 3)
var output, x;

output = (function() {
  var i, results;
  results = [];
  for (x = i = 0; i <= 10; x = ++i) {
    if (Math.pow(x, 2) > 3) {
      results.push(2 * x);
    }
  }
  return results;
})();

Squares

squares = (i ** 2 for i in [0..10])
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Stepping

squares = (i ** 2 for i in [0..10] by 2)
[0, 4, 16, 36, 64, 100]

When

multipleOfThree = (i for i in [0..20] when i % 3 is 0)
[0, 3, 6, 9, 12, 15, 18]

Or/And

(j for j in [0..30] when j % 3 is 0 or j % 5 is 0)
[0, 3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27, 30]
(p for p in [0..30] when p % 3 is 0 and p % 5 isnt 0)
[3, 6, 9, 12, 18, 21, 24, 27]

小練習4: 找質數

在0~n之間有哪些質數?

coffee> primes 10
[2, 3, 5, 7]

coffee> primes 50
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

方法1

檢查從2~n中每一個數字能不能被任何數字(不包括1和該數)整除

2: no

3: no

4: 2

5: no

6: 2

7: no

8: 2

9: 3

Example:

primes 10

[2, 3, 5, 7]

方法2

篩法(sieve),原始陣列為2~n,先用2過濾,把2的倍數去掉,再用3過濾,把3的倍數去掉,再用5過濾,把5的倍數去掉......

最後剩下的數字就是質數

埃拉托斯特尼篩法

sieve of Eratosthenes

更多功能...

  • "class" 語法 (物件導向)
  • splats (...)
  • 指定function的scope為"this"
  • generator function (ES6)
  • switch, when, else 語法
  • 連貫比較 (a > b > c)
  • source mapping

FAQ

  • 學CoffeeScript就不用學JavaScript嗎?
  • 使用CoffeeScript可以取代JavaScript?
  • 一定要把*.coffee編譯成*.js才能用?
  • 用CoffeeScript需不需要把其他js全改寫?
  • 有沒有從js轉成coffee的工具?

其他參考資料

Q&A

謝謝大家

歡迎follow我的GitHub XD

http://github.com/adrianliaw

CoffeeScript

By Adrian Liaw

CoffeeScript

  • 1,663