CoffeeScript

今天和大家介绍一个有趣的东西....

介绍

CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的心脏. CoffeeScript 尝试用简洁的方式展示 JavaScript 优秀的部分.
CoffeeScript 是一门简洁的,构架于JavaScript之上的预处理器语言,可以静态编译成JavaScript,语法主要受ruby和python影响。

优点&&安装

  • 更少,更紧凑,和更清晰的代码
  • 通过规避和改变对JavaScript中不良部分的使用,只留下精华,让代码减少出错率,更容易维护
  • 在很多常用模式的实现上采用了JavaScript中的最佳实践
  • CoffeeScript生成的JavaScript代码都可以完全通过JSLint的检测

安装
最简单的安装和测试CoffeeScript的方法,是使用node.js的npm安装,然后使用命令行脚本实时编译

npm install -g coffee-script
coffee -w --output lib --compile src

什么情况下不推荐使用CoffeeScript?

CoffeeScript不是JavaScript的超集,也不是完全替代品,不应该在不会JavaScript的情况下使用CoffeeScript工作。

CoffeeScript是一种需要预编译的语言,不能在运行时(Runtime)解释,这造成了她普遍被人质疑的一点,就是如果代码中出现运行时错误时难以调试,不过从实际使用上来看,因为CoffeeScript的编译结果大部分情况下自然而合理。

这种静态编译还有一个额外的好处,就是CoffeeScript和现有的环境(浏览器,Node,Rhino等)与库完全兼容

简单介绍入门

注释
在coffeeScript中,注释均采用 # 符号

# single line comment
### 
  multi line comment
###    

关于语句后加  的问题

在js中,如果认为当前语句和随后语句是一个整体的话,就不会自己加;,比如以下javascript代码

//javascript code
var y = x+f
(a+b).toString()

//parsed to:
var y = x+f(a+b).toString();

---CoffeeScript在编译时为每条语句加上;,因此在代码中不需要写;

作用域

在js中最糟糕的设计就是全局变量,当你忘记用var声明变量的时候,这个变量会成为全局对象上的一个属性
CoffeeScript避免了这点

输入:foo = "bar"

编译后:

(function() {
  var foo;
  foo = "bar";
}).call(this);

任何的代码都会使用Immediate Function包装,这样foo成为了本地变量,并且,可以通过call指定的this引用全局对象

为了方便起见,之后的编译后代码描述不会再加上这个包装

实际上在CoffeeScript中,你也不需要再用var声明变量,编译后会自动加上var,并且将声明hoisting,即放到作用域的顶部,看一个来自官方文档的例子
输入:

outer = 1
change = ->
  inner = -1
  outer = 10
inner = change()

->是函数定义的简写方式,之后我们会探讨(当时使用的是ES2015还未有ES6的剪头语法)
编译后:

var change, inner, outer;

outer = 1;

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

inner = change();

赋值

首先是字符串可以用类ruby的语法内嵌

target = "world"
alert "hello, #{target}"

其次是字面量,可以用类似YAML的方法定义对象字面量

object1 = one: 1, two: 2
object2 =
  one: 1
  two: 2
  class: "numbers"

注意保留字class,现在可以直接作为对象的key了

数组也可以分行

arr = [
  1
  2
]

数组

数组的操作引入了来自ruby的Range概念,并且可以将字符串完全作为数组操作

numbers = [0..9]
numbers[3..5] = [-3, -4, -5]
my = "my string"[0..1]

判断一个值是否在数组内,在js中可以用Array.prototype.indexOf,不过IE8及以下不支持,CoffeeScript提供了跨浏览器的in操作符解决

arr = ["foo", "bar"]
"foo" in arr

编译后:

 var arr,
   __indexOf = [].indexOf || function(item) { 
     for (var i = 0, l = this.length; i < l; i++) { 
       if (i in this && this[i] === item) 
         return i; 
     } 
     return -1; 
   };

arr = ["foo", "bar"];

__indexOf.call(arr, "foo") >= 0;

也具有过滤器when

prisoners = ["Roger", "Roderick", "Brian"]
release prisoner for prisoner in prisoners when prisoner[0] is "R"

看起来很像普通英语了,也可以用()收集遍历的结果

result = (item for item in array when item.name is "test")

流程控制

CoffeeScript使用来自ruby的省略语法,让控制流变得很紧凑,也引进了unless,not,then等语法糖式的关键字

result = if not true then "false"
result = unless true then "false"

取消了js中的==判断,改成全部用===进行严格比较,js中的==会做大量诡异的类型转换,很多情况下是bug的来源

if "1" == 1 
  alert("equal")
else
  alert("not equal")

在使用if来进行空值的判断时,js有时会让人困扰,因为""和0都会被转换成false,Coffee提供了?操作符解决这个问题,她只有在变量为null或undefined时才为false

""? #true
null? #false

也可以用常见的类似ruby中||=的方法,判断赋值,此外还可以用and,or,is关键字代替&&,||,==

hash or= {}
hash ?= {}

经常有当某个属性存在的时候,才会调用属性上的方法的情况,这时候也可以用?

knight.hasSword()?.poke()

只有当hasSword()返回对象不为空时,才会调用poke方法,以下是编译的js代码

var _ref;
if ((_ref = knight.hasSword()) != null) {
  _ref.poke();
}

switch case语句也有了一些语法糖,并且会默认加上break

switch day
  when "Sun" then go relax
  when "Sat" then go dancing
  else go work

函数

CoffeeScript对JavaScript的函数做了很大的简化,举个例子,看一个求和函数

sum = (nums...) ->
  nums.reduce (x, y) -> x+y

sum 1,2,3

对应JavaScript

var sum,
    __slice = [].slice;

sum = function() {
  var nums;
  nums = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  return nums.reduce(function(x, y) {
    return x + y;
  });
};

sum(1, 2, 3);
  • 可以使用和ruby 1.9类似的lambda函数写法->来代替function
  • 参数列表放在->的前边,且可省略
  • 取消了函数声明,只能将函数作为值定义
  • 在CoffeeScript中,任何语句都是表达式(除了break和continue),都有返回值,因此像ruby一样,不需要显- 式return
  • js的函数参数有一个很讨厌的地方,就是参数对象arguments不是一个真正的数组,要使用数组方法,必须- 转换成数组[].slice.call(arguments, 0)这样,而在CoffeeScript中收束(加...)的参数是一个真正的数组

CoffeeScript的函数可以有默认参数,如

times = (a = 1, b = 2) -> a * b

CoffeeScript的函数调用可以不用()语法包围参数,像ruby一样跟在函数名后面就可以,不过这也有时候会带来问题,特别是没有参数的调用
alert

总结

如果有兴趣的小伙伴,可以到coffeeScript中文网 ,继续学习。
虽然是一个糖果版的JavaScript,但是还是 给予javaScript,对于学习专研,还是要以javaScript为准。至于CoffeeScript是一个非常好的书写规范,让javaScript更加简洁易懂。ES6的出现也是根据CoffeeScript的亮点进行优化的。所以目前ES6已经覆盖了CoffeeScript的70%的功能点了。随着ES2017将在6月份推出,相信有更多的惊喜值得我们发现!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容