初識 CoffeeScript

很早就知道這CoffeeScript一門語言,可是一直沒有機會系統的學習下,那天趁在公司沒有什麼要緊的項目作,就根據CoffeeScript首頁的例子學了一下。javascript

引用CoffeeScript的一段介紹:html

CoffeeScript 是一門編譯到 JavaScript 的小巧語言. 在 Java 般笨拙的外表下, JavaScript 其實有着一顆華麗的心臟. CoffeeScript 嘗試用簡潔的方式展現 JavaScript 優秀的部分. CoffeeScript 的指導原則是:  "她僅僅是 JavaScript". 代碼一一對應地編譯到 JS, 不會在編譯過程當中進行解釋. 已有的 JavaScript 類庫能夠無縫地和 CoffeeScript 搭配使用, 反之亦然. 編譯後的代碼是可讀的, 且通過美化, 能在全部 JavaScript 環境中運行, 而且應該和對應手寫的 JavaScript 同樣快或者更快.

---- 來自CoffeeScript中文java

本身是寫PHP的,最開始接觸CoffeeScript的時候,就被他吸引了,由於它居然能夠不用括號、分號就能夠識別語法規則,在用jQuery編寫一些事件的時候常常會寫回調函數,經常在最後留下一大串的 }); node

使用CoffeeScript就能夠寫出很優美的Js的代碼了,另外還能夠很好的避免局部變量由於不加var而引用到全局變量。而形成一些莫名其妙的錯誤。git

下面是本身的一些筆記:github

1、安裝

由於CoffeeScript是基於nodejs的,因此首先須要安裝nodejs (這傢伙也不錯,竟然可讓js運行在服務端),在nodejs下載相應平臺的版本就能夠了,我這裏使用CentOS系統。npm

wget -c http://nodejs.org/dist/v0.10.26/node-v0.10.26.tar.gz
tar -zxvf node-v0.10.26.tar.gz -C /usr/local/src/
cd /usr/local/src/
./configure
make && make install

當安裝成功了後可使用segmentfault

npm -v數組

測試是否安裝成功~   若是沒有該命令看看是否是PATH沒有加入。瀏覽器

使用npm包管理工具安裝CoffeeScript(爲了加快安裝速度,可使用淘寶NPM鏡像)

安裝CoffeeScript

npm install -g coffee-script

肯定安裝成功

coffee -v
CoffeeScript Version 1.7.1

 

2、Hello World

2.1編譯一個第一個coffeeScript文件

coffee命令參數:

-c, --compile 編譯一個 .coffee 腳本到一個同名的 .js 文件.
-m, --map 隨 JavaScript 文件一塊兒生成 source maps. 而且在 JavaScript 里加上 sourceMappingURL 指令.
-i, --interactive 啓動一個交互式的 CoffeeScript 會話用來嘗試一些代碼片斷. 等同於執行coffee 而不加參數.
-o, --output [DIR] 將全部編譯後的 JavaScript 文件寫到指定文件夾. 與 --compile 或 --watch 搭配使用.
-j, --join [FILE] 編譯以前, 按參數傳入順序鏈接全部腳本到一塊兒, 編譯後寫到指定的文件. 對於編譯大型項目有用.
-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]"
-b, --bare 編譯到 JavaScript 時去掉頂層函數的包裹.
-t, --tokens 不對 CoffeeScript 進行解析, 僅僅進行 lex, 打印出 token stream:[IDENTIFIER square] [ASSIGN =] [PARAM_START (] ...
-n, --nodes 不對 CoffeeScript 進行編譯, 僅僅 lex 和解析, 打印 parse tree:
Expressions
  Assign
    Value "square"
    Code "x"
      Op *
        Value "x"
        Value "x"
--nodejs node 命令有一些實用的參數, 好比 --debug--debug-brk--max-stack-size, 和 --expose-gc. 用這個參數直接把參數轉發到 Node.js. 重複使用 --nodejs 來傳遞多個參數.

我習慣 這麼用:coffee -c -w -o ./js hello.coffee 這樣就能夠就能夠通常編寫一邊編譯,並把編譯後的js文件放到指定的文件夾中。

寫一個coffee文件:

#打印出Hello World
Console.log "Hello World"

編譯命令:

coffee -c hello.coffee

會在同級目錄下生成一個同名的js文件。

能夠直接使用node命令執行js文件 或者在html中引入讓瀏覽器來執行 ,這裏用node直接執行:

node hello.js

Hello World!完成 咱們看看coff幫咱們編譯成了什麼樣子的js。

// Generated by CoffeeScript 1.7.1
(function() {
console.log("Hello World!");
}).call(this);

CoffeeScript 將js包裹在了一個匿名函數當中,並用call(this)調用,這樣使得js代碼隔離,不會和外部混淆。

 2.2 做用域

在js中定義變量須要加上var,可是在CoffeeScript中你不須要這樣作,直接

age=22
name="silenceper"
say=(arg)->
 console.log "my name is "+arg
say name

對應的js以下:

// Generated by CoffeeScript 1.7.1
(function() {
 var age, name, say;

 age = 22;

 name = "silenceper";

 say = function(arg) {
 var str;
 str = "my name is " + arg;
 return console.log(str);
 };

 say(name);

}).call(this);

能夠看到全部的全局變量都會被定義在最頂層,函數內部的局部變量也被加上var定義,防止和局部變量混淆。這一點很是有用,以前就遇到過這樣的問題,由於定義了一個變量,恰好這個變量就是dom的id,而我又沒有加上var聲明,致使ie認爲這是一個dom對象,而出現一些莫名奇妙的錯誤,固然還有不少,相信寫js的人也遇到過這樣的問題。

2.3 函數

我已經在上面使用了函數,它是經過->的形式來定義一個函數,有參數的話就在前面的括號中寫參數,而後經過空格 縮進來表示函數體。

2.4  if/else/unless

其實跟js差很少  只不過使用起來更加方便了,它不須要你加括號、分號來區分,這裏也是使用空格、縮進來處理。

day="Thursday"
if day is "Saturday" or "Sunday"
    go "rest"
else
    go "work"

coffeeScript跟js中判斷的對比

javascript與CoffeeScript判斷比較

還有存在性判斷:就是在變量的後邊加上一個?

solipsism = true if mind? and not world?

speed = 0
speed ?= 15

footprints = yeti ? "bear"

2.5 循環

使用for/in 完成數組的循環,使用for/of 完成對象的循環

for/in示例:

eat food for food in ['toast', 'cheese', 'wine']

對於的js

var _ref,food,_i;
_ref = ['toast', 'cheese', 'wine'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  food = _ref[_i];
  eat(food);
}

for/of 示例:

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

ages = for child, age of yearsOld
  "#{child} is #{age}"

注意:其中的#{}就是變量的替換

2.6  switch/when/else

使用官方的示例:

 

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

對應的js:

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);
}

2.7 類/繼承

直接參考官方的示例:

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()

對應的js:

var Animal, Horse, Snake, sam, tom,
  __hasProp = {}.hasOwnProperty,
  __extends = 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; };

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

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

  return Animal;

})();

Snake = (function(_super) {
  __extends(Snake, _super);

  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(_super) {
  __extends(Horse, _super);

  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();

其實在javascript當中並無class,extends 這樣的用法,只不過爲了讓使用起來方便,CoffeeScript容許你這樣簡單的使用。

經過觀察編譯後的js發現,它是經過一個__extends方法來實現繼承這一用法的,其實也是經過更改prototype來實現。

其中的@name 表示的就是this.name

CoffeeScript爲了方便使用prototype,可使用雙冒號來替代prototype。

說說註釋:

單行註釋:使用一個#,這種註釋方式不會被編譯進js當中

#這是單行註釋

多行註釋:使用三個#開始,三個#結束。這種註釋方式會被編譯爲/**/的形式

###
這是多行註釋
###

其實CoffeeScript當中還有不少奇妙便捷的功能,你能夠在CoffeeScript首頁的例子中找到。

 

在github中能夠找到不少CoffeeScript寫的js項目,能夠多看看!

另外還有一個js轉CoffeeScript的工具:https://github.com/js2coffee/js2coffee


原文地址:http://silenceper.com/archives/1108.html

相關文章
相關標籤/搜索