coffeescript
安装:
npm install -g coffee-script(全局)
预编译:
coffee –compile my-script.coffee
注释:
# (单行) ###(多行)
变量与作用域:
- 变量和赋值是局部的
- 全局变量用this.
函数:
- 瘦箭头->表示function语句,
- 函数的最后一个表达式会作为隐式的返回值
eg.
func = -> "bar" var func;
func = function() {
<==> return "bar";
};
函数参数:
- 指定参数:times = (a, b) -> a * b
- times = (a = 1, b = 2) -> a * b
使用参数槽(splats)接收多个参数,使用…表示:
sum = (nums...) -> result = 0 nums.forEach (n) -> result += n result
在上面的例子中,nums是一个包含传递给函数全部参数的数组。它不是一个arugments对 象,而是一个真实的数组对象,这样的话在你想操作它的时候就不需要先使用 Array.prototype.splice或者jQuery.makeArray()了。
trigger = (events…) ->
events.splice(1, 0, this)
this.constructor.trigger.apply(events)
函数调用:
函数上下文:
胖箭头代替普通箭头是为了确保函数的上下文可以绑定为当前的上下文
this.clickHandler = -> alert "clicked"
element.addEventListener "click", (e) =>this.clickHandler(e)
原因:来自addEventListener的回调函数会以element为上下文 被调用,也就是说,this就相当于这个元素。如果你想让this等于当前上下文,除了使用 self=this,胖箭头也是一种方式。
流程控制
- 可省略(),例如:if,else
在单行的if语句中,需要使用then关键字,这样CoffeeScirpt才能明白执行体从什么地方开始。CoffeeScript并不支持条件运算符,作为替代你应该使用单行的if/else 语句。
if true != true then "Panic" # equivqlent to: # (1 > 0) ? "ok" : "y2k!" if 1 > 0 then "Ok" else "Y2K!"
CoffeeScript还支持一项Ruby的特性,即运行在if语句前使用前缀表达式 alert “It’s cold!” if heat < 5
- 使用not关键字来代替感叹号(!)来做取反操作
- is语句,编译过去就是===,isnt代替is not
- CoffeeScript会把==操作符转化为===,把!=转化为! ==
字符串插入
在双引号的字符串中可以 包含#{}标记,这些标记中可以包含被插入到字符串中的表达式。
favourite_color = "Blue. No, yel..."
question = "Bridgekeeper: What... is your favourite color?
Galahad: #{favourite_color}
Bridgekeeper: Wrong!
"
循环和列表解析
循环
for name in ["Roger", "Roderick", "Brian"]
alert "Release #{name}"
获取索引
for name, i in ["Roger the pickpocket", "Roderick the robber"]
alert "#{i} - Release #{name}"
一行代码完成迭代。
release prisoner for prisoner in ["Roger", "Roderick", "Brian"]
过滤:
prisoners = ["Roger", "Roderick", "Brian"]
release prisoner for prisoner in prisoners when prisoner[0] is "R"
使用推导式来迭代对象的全部属性,不过要使用of代替in关键字。
names = sam: seaborn, donna: moss
alert("#{first} #{last}") for first, last of names
数组
- 使用两个数字来定义区间, 分别代表区间的第一个和最后一个位置。这两个数字之间使用..或…来分隔
- 如果区间之 前没有任何东西,CoffeeScript会将其转换为一个数组
如果区间被指定到一个变量之后,CoffeeScript则会将其转换为一个slice()调用
firstTwo = ["one", "two", "three"][0..1]
区间会返回一个只包含原始数组的前两个元素的新的字符串。你也可以使 用同样的语法来把数组中的某个片段替换为其他的数组
numbers = [0..9] numbers[3..5] = [-3, -4, -5]
- JavaScript还能让你在字符串上调用slice(),因此你可以在字符串上使用区间 来获得一个新的子字符串。my = “my string”[0..2]
检测数组中是否存在某个值,使用in操作符
words = ["rattled", "roudy", "rebbles", "ranks"] alert "Stop wagging me" if "ranks" in words
别名和存在操作符
- @,是this的别名
- ::,prototype的别名
- 存在操作符?只会在变量为null或者 undefined的时候会返回真,还能用它来替换||操作符
类
CoffeeScript使用JavaScript原生的原型来产生类,为静态变量继承以及上下文持久 化添加了一点语法糖,而暴露给开发者的全部只有一个class关键字
class Animal
Animal是类的名字,而且也是你可以用来创建实例的合成的变量的名字。 CoffeeScript在背后使用了一个构造函数,这意味着你可以使用new关键字来实例化变量。
animal = new Animal
- 定义构造函数(在实例化前调用的函数)很简单,使用名为constructor的函数
- 如果在参数前 加一个@,CoffeeScript就会在构造函数中自动地把参数设置为实例的属性
实例属性
可以非常直接地为类添加实例属性,与为对象添加属性的语法一样。只需要在类体内对属性采用合理的缩进即可
class Animal price: 5 sell: (customer) -> animal = new Animal animal.sell(new Customer)
- 实例方法上使用胖箭头你就能确保方法能在正确的上下文中执行——this总是 等于当前的实例对象。
静态变量
使用@作为this的别名,这能让你更加便捷的定义静态属性:
class Animal
@find: (name) ->
Animal.find("Parrot")
继承与Super
使用extends关键字来使用继承
class Animal constructor: (@name) -> alive: -> false class Parrot extends Animal constructor: -> super("Parrot") dead: -> not @alive()
CoffeeSript使用原型继承来自动的从类实例上继承所有的属性,这保证了类的动态性
- 就算 你给一个已经被子类继承了的父类添加属性,这些属性仍然可以被其子类继承过来
- 静态变量是直接拷贝给子类的,而不是像实例属性那样通过原型来实现
Mixins
较之于继承只能实现 从单一的父类继承,Mixins的优势是能够实现多个继承。
extend = (obj, mixin) ->
obj[name] = method for name, method of mixin
obj
include = (klass, mixin) ->
extend klass.prototype, mixin
# Usage
include Parrot,
isDeceased: true
(new Parrot).isDeceased
扩展类
把Mixins集成到CoffeeScript的类中 吧。我们将会定义一个名为Module的类,然后可以继承这个类来获得对Mixins的支持Module会有两个静态方法,@extend()和@include(),可以用它们来实现对类的静态属 性和实例属性的扩展。
CoffeeScript惯用法
Each
myFunction(item) for item in array
这种语法易读简洁(我想你也这么认为),而且更棒的是这在背后会被编译为for循环。换 句话说CoffeeScript的语法提供了forEach()的便捷,但是没有性能的损耗,也不需要shim 的辅助。
map
使用列表解析获得与map()同样的行为。注意最好使用括号 把列表解析包裹起来,以便能够完全地确保列表解析返回你所想要的东西——映射后的数组。
result = (item.name for item in array)
筛选
CoffeeScript的基础语法使用when关键字通过一个比较来过滤数组项。在背后会产生一个for循环,整个运行过程都包裹在一个匿名函数中,以防止作用域泄漏或变量冲突。
result = (item for item in array when item.name is "test")
别忘了使用括号,否则result是数组的最后一项。
包含
in方法。
included = "test" in array
在背后,CoffeeScript使用的是 Array.prototype.indexOf(),必要的话提供shim方法 来检测数组中是否有某个特定值,不幸的的是同样的in语法并不能在字符串中工作。我们 退回去使用indexOf()函数,查看其返回值是否是负值:
属性迭代
of方法:
object = {one: 1, two: 2}
alert("#{key} = #{value}") for key, value of object
如你所见,你可以同时指定属性名和属性值,非常方便。
Min/Max
Math.max 和 Math.min接受多个参数
因此你可以简单的地使用…来向它们传递数组,从中检索出最 大值和最小值。
Math.max [14, 35, -7, 46, 98]... # 98
Math.min [14, 35, -7, 46, 98]... # -7
这个技巧对于超大的数组也会失败,因为浏览器对传递个函数的参数数量有限制
多个参数
使用…来结构数组作为多个参数传递给max方法。在背 后,CoffeeScript将其转化为一个使用appply()的函数调用,以确保数组能够作为多个参 数传递给max。在别的地方也可以使用这个特性,比方说代理函数:
And/or
CoffeeScript编程风格推荐使用or代替||,使用and代替&&,
可以使用is代替==,isnt代替!=
私有变量
CoffeeScript中的do关键字能够让我们立即运行函数,这是一种非常有效的包装作用域和受 保护变量的方式
CoffeeScript的自动编译
Cake
Cake是一个超级简单的与 Make和 Rake类似的构建工具。该库被捆绑在coffee-script 的npm安装包中,可以通过名为cake的可执行程序来使用。