CoffeeScript笔记

CoffeeScript笔记

参考资料:
CoffeeScript 笔记
coffeescript中文
coffeescript英文

CoffeeScript 是一门编译到 JavaScript 的小巧语言.

CoffeeScript 的指导原则是: “她仅仅是 JavaScript”. 代码一一对应地编译到 JS, 不会在编译过程中进行解释。 已有的 JavaScript 类库可以无缝地和 CoffeeScript 搭配使用, 反之亦然。 编译后的代码是可读的, 且经过美化, 能在所有 JavaScript 环境中运行, 并且应该和对应手写的 JavaScript 一样快或者更快.

通过npm 全局安装coffeescript

npm install coffeescript -g

「语法糖」可以理解为让代码的读写更简单。

概例

# 赋值:
number   = 42
opposite = true

# 条件:
number = -42 if opposite

# 函数:
square = (x) -> x * x

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

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

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

# 存在性:
alert "I knew it!" if elvis?

# 数组 推导(comprehensions):
cubes = (math.cube num for num in list)

对应的js:

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

语法

1.有意义的空格

CoffeeScript 移除了所有的大括号和分号。

CoffeeScript 使用显式的空白来区分代码块. 你不需要使用分号 ; 来关闭表达式, 在一行的结尾换行就可以了(尽管分号依然可以用来把多行的表达式简写到一行里). 不需要再用花括号来 { } 包裹代码快, 在 函数, if 表达式, switch, 和 try/catch 当中使用缩进.

2.变量作用域的控制

CoffeeScript 把编译生成的 JS 封装在一个匿名函数中:

(function(){
  // 这里是编译生成的代码
}).call(this);

这样就巧妙避免了全局作用域的污染。同时,CoffeeScript 始终在编译生成的 JS 代码中用 var 声明变量。

3.存在性判断

CoffeeScript 中有个操作符 ?,用于检测变量是否存在。

console.log html if html?

这句 CoffeeScript 编译过来为(去掉了匿名封装函数,为了方便,之后的编译后代码都去掉)

if (typeof html !== "undefined" && html !== null) {
  console.log(html);
}

可见,? 会先检测变量有没有定义,如果定义了再检测是否为 null。

4.函数和 splat 操作符

CoffeeScript 中去掉了 function 关键字。用 () -> 定义一个函数。空函数看起来像这样:->。括号内为参数,可以为参数设置默认值。当传入的参数不存在 (null 或者 undefined) 时,默认值会被使用.如:

myFunction = (a, b = 2) ->
  a + b

编译为:

var myFunction;

myFunction = function(a, b) {
  if (b == null) {
    b = 2;
  }
  return a + b;
};

调用函数的时候,还可以不用括号。如:

myFunction 3, 5

有一点需要注意一下,CoffeeScript 会在编译后的 JS 代码中自动为最后一行添加 return 关键字。所以不论函数的最后一行是什么,都会成为返回值。如果你不想让最后一行成为返回值,就需要另起一行自己加上 return

splat 操作符非常强大。在你的函数需要接受可变数量的参数时就需要它了。书上的例子:

splatter = (etc...) ->
  console.log "Length: #{etc.length}, Values: #{etc.join(', ')}"
  // CoffeeScript 中字符串插值用 #{}

splatter()
splatter("a", "b", "c")

// 输出
Length: 0, Values:
Length: 3, Values: a, b, c

就在某个参数后面加上...,就使传入的参数自动转化为一个数组。splat 操作符可以出现在参数列表的任意位置,但是参数列表中只能有一个 splat 操作符

5.数组与区间

一般定义数组是这样:

myArray = ["a", "b", "c"]

在 CoffeeScript 里你还可以这样:

myArray = [
            "a"
            "b"
            "c"
          ]

如果单个属性被写在自己的一行里, 那么逗号是可以省略的.

  • 在 JS 中判断是否存在于数组,需要用 Array.prototype.indexOf,在 CoffeeScript 中只需要用 in
console.log "d was not be found" unless "d" in myArray

// 输出
d was not be found
  • 推导式
eat food for food in ['toast', 'cheese', 'wine']

编译成

var food, _i, _len, _ref;

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

在推导式中使用by子句,可以实现以固定跨度迭代范围值: evens = (x for x in [0..10] by 2)

推导式也可以用于迭代对象中的key和value。在推导式中使用of 来取出对象中的属性,而不是数组中的值。

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

ages = for child, age of yearsOld
  "#{child} is #{age}"
  • 交换赋值
x = "X"
y = "Y"

[x, y] = [y, x]

交换 x、y 的值就这么简单!

  • 多重赋值(解构赋值)
myArray = ["A", "B", "C", "D"]

[start, middle..., end] = myArray  // 可配合 splat 操作符使用

console.log "start: #{start}"
console.log "middle: #{middle}"
console.log "end: #{end}"

// 输出
start: A
middle: B,C
end: D
  • 区间

区间(range)能让定义包含两个数字之间所有数字的数组变得很容易。

myRange = [1..10]
console.log myRange

// 输出 [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

如果不想包括结束数值,可以用 ... 代替 ..

myRange = [10...1]
console.log myRange

// 输出 [ 10, 9, 8, 7, 6, 5, 4, 3, 2 ]

常见的数组操作,都可以通过区间完成:

myArray = [1..10]

// 分割数组
// 前面的索引位置省略的话, 默认会是 0, 后面的索引位置被省略的话, 默认值是数组的大小.索引位置值可以是负数,表示逆序。
part = myArray[0..2]
console.log part
// 输出 [ 1, 2, 3 ]

// 替换数组值
myArray = [1..10]
// 前面的值startIndex是索引位置,后面的值endIndex等于endIndex-startIndex+1
myArray[4..7] = ["a", "b", "c", "d"]
console.log myArray
// 输出 [ 1, 2, 3, 4, 'a', 'b', 'c', 'd', 9, 10 ]

// 插入值
myArray = [1..10]
// 如果startIndex>endIndex,则为插入操作,反之则为替换
myArray[4..-1] = ["a", "b", "c", "d"]
console.log myArray
// 输出 [ 1, 2, 3, 4, 'a', 'b', 'c', 'd', 5, 6, 7, 8, 9, 10 ]
6.操作符和 aliase

CoffeeScript 会把 == 编译为 ===, 把 != 变异为 !==.

until关键字等同于while not, loop关键字 等同于while true。在 while, if/else, switch/when 的语句当中, then 可以被用来分隔判断条件跟表达式, 这样就不用强制写换行或者分号了.

CoffeeScript 引入了很多别名来代替一些关键字:

别名对应关键字
is===
isnt!==
not!
and&&
or||
true, yes, ontrue
false, no, offfalse
@, thisthis
of (探测 JavaScript 对象的属性是否存在)in
in (判断数据在数组中是否出现)no JS equivalent
a ** b (乘方)Math.pow(a, b)
a // b (整除)Math.floor(a / b)
a %% b (模运算)(a % b + b) % b
7.类和继承

一例胜千言:

class Animal
  constructor: (@name) ->

  // 用 @property: value 赋值静态的属性
  @type'animal'

  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()
  • consturctor 函数为类的构造函数。在 new 的时候调用,可以重写它。
  • :: 就和 JS 里的 prototype 一样
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值