资讯专栏INFORMATION COLUMN

初识 CoffeeScript

骞讳护 / 2483人阅读

摘要:而造成一些莫名其妙的错误。写一个文件打印出编译命令会在同级目录下生成一个同名的文件。将包裹在了一个匿名函数当中,并用调用,这样使得代码隔离,不会和外部混淆。其中的表示的就是为了方便使用,可以使用双冒号来替代。

很早就知道这CoffeeScript一门语言,但是一直没有机会系统的学习下,那天趁在公司没有什么要紧的项目做,就根据CoffeeScript首页的例子学了一下。

引用CoffeeScript的一段介绍:

CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的心脏. CoffeeScript 尝试用简洁的方式展示 JavaScript 优秀的部分.

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

---- 来自CoffeeScript中文

自己是写PHP的,最开始接触CoffeeScript的时候,就被他吸引了,因为它竟然可以不用括号、分号就可以识别语法规则,在用jQuery编写一些事件的时候经常会写回调函数,常常在最后留下一大串的 });

使用CoffeeScript就可以写出很优美的Js的代码了,另外还可以很好的避免局部变量因为不加var而引用到全局变量。而造成一些莫名其妙的错误。

下面是自己的一些笔记:

一、安装

因为CoffeeScript是基于nodejs的,所以首先需要安装nodejs (这家伙也不错,居然可以让js运行在服务端),在nodejs下载相应平台的版本就可以了,我这里使用CentOS系统。

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

当安装成功了后可以使用

npm -v

测试是否安装成功~   如果没有该命令看看是不是PATH没有加入。

使用npm包管理工具安装CoffeeScript(为了加快安装速度,可以使用淘宝NPM镜像)

安装CoffeeScript

npm install -g coffee-script

确定安装成功

coffee -v
CoffeeScript Version 1.7.1

 

二、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:
--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中判断的对比

还有存在性判断:就是在变量的后边加上一个?

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78073.html

相关文章

  • TypeScript 初识

    摘要:当你陷在一个中大型项目中时应用日趋成为常态,没有类型约束类型推断,总有种牵一发而动全身的危机和束缚。总体而言,这些付出相对于代码的健壮性和可维护性,都是值得的。目前主流的都为的开发提供了良好的支持,比如和。参考资料中文文档 文章博客地址:http://pinggod.com/2016/Typescript/ TypeScript 是 JavaScript 的超集,为 JavaScrip...

    iliyaku 评论0 收藏0
  • 来点CoffeeScript吗?

    摘要:一般来说,可以缩短大约的代码长度。这就避免了意外创建全局变量。使用表示,不推荐的和将不能使用。因此,使用将是有效的解决方法之一。 简单易懂的介绍 CoffeeScript是什么? 首先,它是一门小巧的编程语言。有一本关于CoffeeScript的指南,写作The Little Book on CoffeeScript: showImg(https://segmentfault.com/...

    KavenFan 评论0 收藏0
  • [译] 从 CoffeeScript 迁移到 ES6

    摘要:语法校验会给出警告当你仍在使用或不通过任何关键字声明变量时。但是如果脚本中还有其他的普通导出,就会得到非常奇怪的结果这个坑爹的情况目前还没有任何好的解决方案。 我在多年前爱上了coffeScript。对于javaScript,我一直保持着深沉的爱,也十分高兴得看到node.js的快速发展,但是作为一个有python背景的程序员,我更喜欢coffeeScript的简练语法。 在任何一个活...

    刘东 评论0 收藏0
  • 十个CoffeeScript一行程序——震惊你的小伙伴

    摘要:在自己的博客上分享了十则的一行程序,展示了强大的表达力。你可以把这个页面发给你的小伙伴也许还有妹纸,让他们震惊一下下。它允许你将一个数组作为一组参数传递。和均接受可变参数,例如返回。 Ricardo Tomasi在自己的博客上分享了十则CoffeeScript的一行程序,展示了CoffeeScript强大的表达力。你可以把这个页面发给你的小伙伴(也许还有妹纸),让他们震惊一下下。 s...

    taowen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<